首先需要把对应的函数开放出来,使用如下的宏:
#ifdef EXPORTDLL_EXPORTS
#define EXPORTDLL extern "C" __declspec(dllexport)
#else
#define EXPORTDLLextern "C" __declspec(dllimport)
#endif
通过参数返回数据,在C++中通过引用变量来实现(实测通过C++调用C++的DLL,并不需要引用,即不需要&,但是C#调用就需要,为什么?),如
EXPORTDLL int test(char* &url, char* &type, char* &add)
在C#中引用时,通过ref来返回数据。C++中的char*,在C#中可以用指针IntPtr来对应,也可以用StringBuilder,用指针时,需要给指针初始化并给予足够的大小,用StringBuilder时,只要new StringBuilder()就可以,在C++中会自动分配 。实测需要分配给足够的大小,否则程序会偶尔出错。
用指针如下:
[DllImport("test.dll", EntryPoint = "test", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int test(ref IntPtr url,ref IntPtr type,ref IntPtr add);
通过以下方法取对应的字符串:
Marshal.PtrToStringAnsi(a1)
用StringBuilder如下:
public static extern int test(ref StringBuilder url,ref StringBuilder type,ref StringBuilder add);
StringBuilder url=new StringBuilder();
取值就很方便了。建议用StringBuilder 。
由于水平问题,在实际调试中,C++函数中能给参数赋值,但是跳出后变量值就清空了,原因是内存已经释放,所以在C++给返回变量赋值的时候,一定要用复制,不能直接**赋值 **。在此做记录,以免忘记。
strcpy(url, u2.c_str());
strcpy(type, t2.c_str());
strcpy(add, a2.c_str());
也可以用
_snprintf_s
通过这样的复制,就把实际的值复制给对应的参数所指的内存了。函数结束时这些内存并不会被释放。在C#中,
顺便记录下,C++返回结构体,在C#中的调用
C++中结构体:
struct teststruct{
struct teststruct* pNext;
char* url;
char* st;
char buffer[2];
};
C#中也要先对应一个结构体如下:
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct teststruct
{
public IntPtr pNext;//teststruct结构体引用的自身,链表
public IntPtr url;
public IntPtr st;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] buffer;
}
C++中函数
EXPORTDLL struct teststruct test()
C#中调用
[DllImport("test.dll", EntryPoint = "test", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern UPNPreturn Set_UPNP();
具体调用:
IntPtr struct1= Marshal.AllocHGlobal(1024);
struct1= test();
StringBuilder ss = new StringBuilder();
while (struct1!= null && struct1.ToInt32() > 0)
{
teststruct struct2= (teststruct)Marshal.PtrToStructure(struct1, typeof(teststruct));
ss.Append(string.Format("url:{0},st:{1}", Marshal.PtrToStringAnsi(struct2.url),
Marshal.PtrToStringAnsi(struct2.st)) + "\r\n");
struct1= struct2.pNext;
}