您的位置:首页 > 编程语言 > C语言/C++

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

2014-09-18 20:59 405 查看
【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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: