C#调用C++ 平台调用P/Invoke 字符串【三】

来源:互联网 发布:淘宝售前客服话术对话 编辑:程序博客网 时间:2024/05/21 08:50

【1】字符串作为输入参数


C++代码:


EXPORTDLL_API int Str_Output( WCHAR *pStr ){if (NULL == pStr){return(-1);}wprintf(L"Str_Output %s\n", pStr);return(0);}


C#代码,定义成string即可:


[DllImport("ExportDll.dll", CharSet=CharSet.Unicode)]public static extern int Str_Output([MarshalAs(UnmanagedType.LPWStr)]string pStr);

测试:

string str = "hjkl;";CExportDll.Str_Output(str);

【2】字符串作为参数,需要进行修改返回


C++代码:


EXPORTDLL_API int Str_Change( WCHAR *pStr, int len ){if (NULL == pStr){return(-1);}for (int ix=0; ix<len-1; ix++){pStr[ix] = 'a' + (ix) % 26;}pStr[len-1] = '\0\0';wprintf(L"Str_Change %s\n", pStr);return(0);}


C#代码,定义成stringBuilder类型

[DllImport("ExportDll.dll", CharSet = CharSet.Unicode)]public static extern int Str_Change([MarshalAs(UnmanagedType.LPWStr)]StringBuilder pStr, int len);

测试:


StringBuilder strBuilder = new StringBuilder(256);CExportDll.Str_Change(strBuilder, 256);

【3】字符串作为返回值


C++代码:


static  WCHAR *g_StrReturn = L"Str_Return";

EXPORTDLL_API WCHAR * Str_Return(){wprintf(L"Str_Return \n");return(g_StrReturn);}

C#代码,将返回值定义成IntPtr,再进行解析:


[DllImport("ExportDll.dll", CharSet = CharSet.Unicode)]public static extern IntPtr Str_Return();

测试:


IntPtr strPtr = CExportDll.Str_Return();string strIntPtr = Marshal.PtrToStringUni(strPtr);

【4】字符串数组作为参数,每个元素长度为10


C++代码:


EXPORTDLL_API int Str_ChangeArr( WCHAR **ppStr, int len ){if (NULL == ppStr){return(-1);}for (int ix=0; ix<len; ix++){if (NULL != ppStr[ix]){lstrcpyn(ppStr[ix], L"abc", 10);}}wprintf(L"Str_ChangeArr \n");return(0);}

C#代码,定义成string[],如果数据需要返出,还必须指定In、Out参数:


[DllImport("ExportDll.dll", CharSet = CharSet.Unicode)]public static extern int Str_ChangeArr([In, Out]string[] ppStr, int len);

测试:


string[] strArr = new string[4] {new string('\0', 10),                                  new string('\0', 10),                                   new string('\0', 10),                                  new string('\0', 10) };CExportDll.Str_ChangeArr(strArr, 4);

【5】释放非托管的内存


C++代码:


EXPORTDLL_API void Str_ParameterOut( WCHAR **ppStr ){if (NULL == ppStr){return;}*ppStr = (WCHAR *)CoTaskMemAlloc(128 * sizeof(WCHAR));lstrcpynW(*ppStr, L"abc", 128);wprintf(L"Str_ReturnOut \n");}

C#代码,此时可以使用两种方式:


自动释放内存,必须使用string接受:


//使用CoTaskMemAlloc方法申请的内存,则会自动调用CoTaskMemFree来释放非托管内存//这就意味了托管代码无需处理内存问题,减轻了托管代码的的复杂度//但.NET只能释放由CoTaskMemAlloc分配的内存,所以如果底层不是使用CoTaskMemAlloc申请的内存,必须定义对应的释放函数[DllImport("ExportDll.dll", CharSet = CharSet.Unicode, EntryPoint = "Str_ParameterOut")]

手动释放内存:


//使用IntPtr接受时,需要手动释放[DllImport("ExportDll.dll", CharSet = CharSet.Unicode, EntryPoint = "Str_ParameterOut")]public static extern void Str_ParameterOuttPtr(ref IntPtr ppStr);

测试:


string strOut = "";CExportDll.Str_ParameterOutString(ref strOut);//手动释放IntPtr strOutIntPtr = IntPtr.Zero;CExportDll.Str_ParameterOuttPtr(ref  strOutIntPtr);string strOut2 = Marshal.PtrToStringUni(strOutIntPtr);Marshal.FreeCoTaskMem(strOutIntPtr);


0 0
原创粉丝点击