C#调用C++ 平台调用P/Invoke 字符串【三】
2014-09-18 20:59
405 查看
【1】字符串作为输入参数
C++代码:
C#代码,定义成string即可:
测试:
【2】字符串作为参数,需要进行修改返回
C++代码:
C#代码,定义成stringBuilder类型
测试:
【3】字符串作为返回值
C++代码:
C#代码,将返回值定义成IntPtr,再进行解析:
测试:
【4】字符串数组作为参数,每个元素长度为10
C++代码:
C#代码,定义成string[],如果数据需要返出,还必须指定In、Out参数:
测试:
【5】释放非托管的内存
C++代码:
C#代码,此时可以使用两种方式:
自动释放内存,必须使用string接受:
手动释放内存:
测试:
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);
相关文章推荐
- C#调用C++ 平台调用P/Invoke 结构体--含有内置数据类型的一维、二维数组、字符串指针【六】
- C#调用C++ 平台调用P/Invoke 结构体--结构体嵌套【八】
- C#调用C++ 平台调用P/Invoke 结构体--输入输出参数、返回值、返出值、结构体数组作为参数【五】
- c#编程指南——平台调用P-INVOKE完全掌握,C#和C++互相调用
- C#调用C++ 平台调用P/Invoke 函数指针/回调函数【二】
- C#调用C++ 平台调用P/Invoke 调用约定【一】
- c#编程指南(十) 平台调用P-INVOKE完全掌握, 字符串和指针
- C#调用C++ 平台调用P/Invoke 错误码LastError【四】
- 平台调用 4000 P-INVOKE完全掌握,C#和C++互相调用
- C#调用C++ 平台调用P/Invoke 结构体--内存对齐方式、union封装【七】
- c#编程指南(九) 平台调用P-INVOKE完全掌握,C#和C++互相调用
- C# 中调用C++ DLL (P/Invoke)
- 通过P/Invoke调用32位C++ DLL时,一定要将平台改为X86
- C# 中调用C++ DLL (P/Invoke)
- C# 中调用C++ DLL (P/Invoke)
- C# 中调用C++ DLL (P/Invoke)
- C# 调用 C++ 传递字符串
- c#编程指南(十) 平台调用P-INVOKE完全掌握, 字符串和指针
- 平台调用P-INVOKE(二)--(封送字符串)
- C#通过p/invoke调用C++ DLL (转)