笔者解决这两个问题,花了很长一段时间,网上提供能正常运行的没有找到,不过一边东拼西凑,一边靠朦还是解决了。先贴上代码:
[DllImport(@"C:\Users\Administrator.SC-201901090132\Desktop\opengl\Dll3\Release\Dll3\Dll3.dll",
EntryPoint = "add",CallingConvention = CallingConvention.Cdecl)] //引入dll,并设置字符集
public static extern int add(int q,int a);
定义了个需要从c#调用c++函数的函数。[DllImport]第一个参数表示我们要加载我们自定义的的c++dll文件。EntryPoint = "add",调用的c++函数接口,至于CallingConvention = CallingConvention.Cdecl,这是重点!就是避免c++与c#的参数类型不一致报错,如下:
ConsoleApplicationdll.dllConsoleApplication1.CPPDLL::acc”的调用导致堆栈不对称。
原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。
请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。”
接着看下add 函数在c++中的定义:
extern "C" _declspec(dllexport)int add(int a,int b);
int add(int a,int b)
{
return a+b;
}
如何编译成dll文件,这里就不赘述。
上面完成了c#调用c++函数。下面使用c++调用c#
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void EKFRenderCallback(int s);
[DllImport(@"C:\Users\Administrator.SC-201901090132\Desktop\opengl\Dll3\Release\Dll3\Dll3.dll",
EntryPoint ="CTOC",CallingConvention = CallingConvention.Cdecl,CharSet = CharSet.Ansi)] //引入dll,并设置字符集
public static extern void CTOC(EKFRenderCallback v);
定义了个代理函数,public delegate void EKFRenderCallback(int s);同时别忘了他上面的注解,同样是为了避免参数类型不匹配,报出如下错误:
System.AccessViolationException:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
我再看下在c++ 中的定义:
extern "C" _declspec(dllexport)void acc(int a, int b);
typedef void(*Render)(int ptr);
static Render reftemp;
extern "C" _declspec(dllexport) void CTOC(Render p);
int add(int a,int b)
{
return a+b;
}
void acc(int a, int b)
{
reftemp(a+b);
}
extern "C" _declspec(dllexport) void CTOC(Render p) {
reftemp = p;
};
不难理解。