在C++中定义接口类,在C#中实现

网上大部分都是C#调用C++的接口,很少有C++调用C#的,更少有在C++中定义接口类,在C#中实现。

千辛万苦,终于找到一个网址:http://www.tuicool.com/articles/AFjY7j

简单翻译一下,


class __declspec(dllexport) CSimpleClass {
public:
int value;

CSimpleClass(int value) : value(value)
{
}

~CSimpleClass()
{
printf("~CSimpleClass\n");
}

void M1()
{
printf("C++/CSimpleClass::M1()\n");
V0();
V1(value);
V2();
}

virtual void V0()
{
printf("C++/CSimpleClass::V0()\n");
}

virtual void V1(int x)
{
printf("C++/CSimpleClass::V1(%d)\n", x);
}

virtual void V2()
{
printf("C++/CSimpleClass::V2()\n", value);
}
};

然后用dumpbin.exe等工具查看符号表,也可以直接用文本文件打开,搜关键字CSimpleClass,找到函数的符号(如果不明白,要进修一下C++编译方面的知识):

[email protected]@[email protected]@@Z    

[email protected]@[email protected]@Z    

[email protected]@[email protected]    

[email protected]@[email protected]@@Z    

[email protected]@[email protected]    

[email protected]@@QAEXXZ    

[email protected]@@UAEXXZ    

[email protected]@@[email protected]    

[email protected]@@UAEXXZ

具体是对应的函数是:

public: __thiscall
CSimpleClass::CSimpleClass(int)    
public:
__thiscall CSimpleClass::~CSimpleClass(void)    

public: class CSimpleClass & __thiscall
CSimpleClass::operator=(class CSimpleClass const
&)    
const
CSimpleClass::`vftable‘    
public: void
__thiscall CSimpleClass::M1(void)    

public: virtual void __thiscall
CSimpleClass::V0(void)    
public: virtual
void __thiscall CSimpleClass::V1(int)    

public: virtual void __thiscall
CSimpleClass::V2(void)

接下来是在C#中,定义:

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
public unsafe struct __CSimpleClass
{
public IntPtr* _vtable;
public int value;
}


    public unsafe class CSimpleClass : IDisposable
{
private __CSimpleClass* _cpp;
private IntPtr* _oldvtbl;

private void InitVtable(__CSimpleClass* ths, IntPtr[] arr, int len)
{
IntPtr* newvtable = (IntPtr*)Memory.Alloc(len * sizeof(IntPtr));
for (int i = 0; i < len; i++)
newvtable[i] = arr[i];
_oldvtbl = ths->_vtable;
ths->_vtable = newvtable;
}

private void ResetVtable(__CSimpleClass* ths)
{
IntPtr* oldvtbl = ths->_vtable;
ths->_vtable = _oldvtbl;
Memory.Free(oldvtbl);
}
// CSimpleClass constructor and destructor
[DllImport("cppexp.dll", EntryPoint = "[email protected]@[email protected]@Z", CallingConvention = CallingConvention.ThisCall)]
private static extern int _CSimpleClass_Constructor(__CSimpleClass* ths, int value);
[DllImport("cppexp.dll", EntryPoint = "[email protected]@[email protected]", CallingConvention = CallingConvention.ThisCall)]
private static extern int _CSimpleClass_Destructor(__CSimpleClass* ths);

// void M1();
// virtual void V0();
// virtual void V1(int x);
// virtual void V2();
[DllImport("cppexp.dll", EntryPoint = "[email protected]@@QAEXXZ", CallingConvention = CallingConvention.ThisCall)]
private static extern void _M1(__CSimpleClass* ths);
[DllImport("cppexp.dll", EntryPoint = "[email protected]@@UAEXXZ", CallingConvention = CallingConvention.ThisCall)]
private static extern void _V0(__CSimpleClass* ths);
[DllImport("cppexp.dll", EntryPoint = "[email protected]@@[email protected]", CallingConvention = CallingConvention.ThisCall)]
private static extern void _V1(__CSimpleClass* ths, int i);
[DllImport("cppexp.dll", EntryPoint = "[email protected]@@UAEXXZ", CallingConvention = CallingConvention.ThisCall)]
private static extern void _V2(__CSimpleClass* ths);

public delegate void V0_Delegate();
public delegate void V1_Delegate(int i);
public delegate void V2_Delegate();

public V0_Delegate _v0_Delegate;
public V1_Delegate _v1_Delegate;
public V2_Delegate _v2_Delegate;

public CSimpleClass(int value)
{
//Allocate storage for object
_cpp = (__CSimpleClass*)Memory.Alloc(sizeof(__CSimpleClass));
//Call constructor
_CSimpleClass_Constructor(_cpp, value);
//Create delegates for the virtual functions
_v0_Delegate = new V0_Delegate(V0);
_v1_Delegate = new V1_Delegate(V1);
_v2_Delegate = new V2_Delegate(V2);
IntPtr[] arr = new IntPtr[3];
arr[0] = Marshal.GetFunctionPointerForDelegate(_v0_Delegate);
arr[1] = Marshal.GetFunctionPointerForDelegate(_v1_Delegate);
arr[2] = Marshal.GetFunctionPointerForDelegate(_v2_Delegate);
//Create a new vtable and replace it in the object
InitVtable(_cpp, arr, 3);
}
public void Dispose()
{
//reset old vtable pointer
ResetVtable(_cpp);
//call destructor
_CSimpleClass_Destructor(_cpp);
//release memory
Memory.Free(_cpp);
_cpp = null;
}
public void M1()
{
_M1(_cpp);
}
public virtual void V0()
{
_V0(_cpp);
}
public virtual void V1(int i)
{
_V1(_cpp, i);
}
public virtual void V2()
{
_V2(_cpp);
}
}


    class CSimpleClassEx : CSimpleClass
{
public CSimpleClassEx(int value)
: base(value)
{
}
public override void V2()
{
Console.WriteLine("C#/CSimpleClassEx.V2()");
}
}

这样就可以试验一下了。如果是在C++中回调C#的集成类,实际上对应的C++中CSimpleClass对象的是:private __CSimpleClass*
_cpp;

在C++中定义接口类,在C#中实现,布布扣,bubuko.com

时间: 2024-10-13 18:45:17

在C++中定义接口类,在C#中实现的相关文章

Sql Server中的数据类型和Mysql中的数据类型的对应关系(转)

Sql Server中的数据类型和Mysql中的数据类型的对应关系(转):https://blog.csdn.net/lilong329329/article/details/78899477 一.SQL SERVER与MySQL数据存储的差异 1.SQL SERVER中的datetime,保留到微秒(秒后小数点3位),而mysql仅保留到秒,转换后是否会影响业务,如果影响,需要新增一个字段专门来存储微秒或者毫秒,虽然mysql中没有时间数据类型的精度到达微秒或者毫秒,但是mysql提供对微秒的

java类中定义接口

今天看到一个java类中定义了接口,写个备忘录,记录一下 1 package com.gxf.test; 2 3 public class Test_interface { 4 public interface show{ 5 public void show(); 6 } 7 static class TestInterface implements show{ 8 9 @Override 10 public void show() { 11 System.out.println("this

Python中的接口类与抽象类

接口类 面向对象中的继承有两种用途:1)可以通过继承做到代码重用,并完成扩展:2)接口继承.所谓的接口继承就是定义一个接口类 Interface,接口类中定义了一些接口(就是函数,但这些函数都没有具体的实现),子类继承接口类,并且实现接口中的功能~ 接口继承可以使得外部调用者无需关心具体的实现细节,可用相同的方式处理继承了特定接口的所有对象,这里的前提是接口类需要做出一个很好的抽象~ class Operate_database(): # 接口类 def query(self, sql): ra

如何使用其他文件中定义的类Python

我在文件a.py中定义了一个类class A(object),现在想在b.py中的类B中某个函数中创建一个A的对象,需要如何操作呢? 我在b的头加了import a.py然后使用语句 obj = A()总是报错http://hi.baidu.com/kxw102/item/bbc7db11a863e00ab88a1a0c 正确的方法应该是:from a import A 下面我们来看看具体的原理:python中是通过名称空间来定位的.import a 是将a这个模块引入, 名称是a:也可以imp

4.2 在SELinux策略中定义客体类

一个策略中一定要包含被SELinux内核和其他客体管理器支持的所有客体类和权限的声明.通常来说,我们作为策略编写者,不用担心创建新的客体类.然而,我们需要理解被定义的客体类来编写出更有效率的SELinux策略.理解客体类和权限声明语法是非常有用的,因为特允许我们理解我们正在使用的策略版本支持的客体类和权限. 添加一个新的客体类和权限 添加一个新的客体类和在一个存在的客体类上修改权限非常复杂的工作,这项工作通常只能在修改系统代码本身的时候进行.不像SELinux策略语言的其他方面,客体类和权限在L

【juincen】Java中的接口interface类比js中的回调函数

前几天在左讯飞语音的时候,无意间意识到java中的接口和js中常用的回调函数有点类似,今天在这儿整理一下思路. interface,Java中的接口,为什么会有这个东西. 一,预留声明 比如两个程序员A和B,A要写一段程序,其中需要调用到B写的程序.这时候A可以写一个接口: public interface Demo{ void deal(); } A要调用的方法先“预留声明”在接口里:deal 然后B去完善这个接口,B写了一个实现类实现了这个Demo接口. A在自己的业务逻辑里面只用调用接口的

JavaScript数据结构——模仿ES6中定义的类似的Set类

1 function Set(){ 2 var items={}; 3 4 this.has=function(value){ 5 return items.hasOwnProperty(value); 6 }; 7 8 this.add=function(value){ 9 if(!this.has(value)){ 10 items[value]=value; 11 return true; 12 } 13 return false; 14 }; 15 16 this.remove=func

Flask中定义模型类的几种情况

from datetime import datetime from werkzeug.security import generate_password_hash, check_password_hash from utils import constants from . import db class BaseModel(object): """模型基类,为每个模型补充创建时间与更新时间""" create_time = db.Column

QT中的QQueue类、C++中的queue类

C++中的queue 实现一种先进先出的数据结构,是一个模板类 头文件 #include<queue> queue<int> Q; //定义一个int型队列 Q.empty(); //返回队列是否为空 Q.size(); //返回当前队列长度 Q.front(); //返回当前队列的第一个元素 Q.back(); //返回当前队列的最后一个元素 Q.push(); //在队列后面插入一个元素, 比如插入数字5: Q.push(5) Q.pop(); //从当前队列里,移出第一个元素