[英]trouble using unmanaged c++ from c# using dllimport
我在将C ++非托管DLL导入C#[winform]时遇到问题。 有人可以帮忙吗?
基本上我只是想在c ++中创建一个字符串安全数组,然后尝试将其发送到C#。
这是我的c ++代码。
extern "C" __declspec(dllexport) BOOL GetStringArr(SAFEARRAY* arr)
{
SAFEARRAY* myArray;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 5;
myArray = SafeArrayCreate(VT_BSTR, 1, rgsabound);
VARIANT* pvData = (VARIANT*)(myArray->pvData);
pvData[0].vt = VT_BSTR;
pvData[0].bstrVal = SysAllocString(L"FirstString");
pvData[1].vt = VT_BSTR;
pvData[1].bstrVal = SysAllocString(L"SecondString");
pvData[2].vt = VT_BSTR;
pvData[2].bstrVal = SysAllocString(L"ThirdString");
pvData[3].vt = VT_BSTR;
pvData[3].bstrVal = SysAllocString(L"FourthString");
pvData[4].vt = VT_BSTR;
pvData[4].bstrVal = SysAllocString(L"FifthString");
arr = myArray;
return true;
}
这是我的C#代码。
[DllImport("MyData.dll", EntryPoint = "GetStringArr")]
public static extern bool GetStringArr([MarshalAs(UnmanagedType.SafeArray)] out Array strServerList);
我从C#调用GetStringArr时遇到异常。 我确定我在做些傻事。 有人可以帮忙吗?
提前致谢。
C ++代码中的几个问题。 您正在返回一个数组,该数组要求参数为SAFEARRAY **。 您还用错误的数据填充了数组,创建了字符串数组,但是正在编写VARIANT。 不知道目的是什么,我将在代码修复中保留变体:
extern "C" __declspec(dllexport) BOOL GetStringArr(SAFEARRAY** arr)
{
SAFEARRAY* myArray;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 5;
myArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
VARIANT* pvData = 0;
SafeArrayAccessData(myArray, (void**)&pvData);
pvData[0].vt = VT_BSTR;
pvData[0].bstrVal = SysAllocString(L"FirstString");
// etc..
SafeArrayUnaccessData(myArray);
*arr = myArray;
return true;
}
C#代码:
object[] array;
bool ok = GetStringArr(out array);
[DllImport(@"blah.dll", EntryPoint = "GetStringArr")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool GetStringArr([MarshalAs(UnmanagedType.SafeArray)] out object[] strServerList);
C和.NET方面的一些问题
在C端
C代码
extern "C" __declspec(dllexport)
BOOL GetStringArr(SAFEARRAY** arr)
{
SAFEARRAY* myArray;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 5;
myArray = SafeArrayCreate(VT_BSTR, 1, rgsabound);
BSTR* pvData = (BSTR*)(myArray->pvData);
pvData[0] = SysAllocString(L"FirstString");
pvData[1] = SysAllocString(L"SecondString");
pvData[2] = SysAllocString(L"ThirdString");
pvData[3] = SysAllocString(L"FourthString");
pvData[4] = SysAllocString(L"FifthString");
*arr = myArray;
return true;
}
在.NET方面
out string[]
获取指向SAFEARRAY的指针 .NET代码
class Program
{
static void Main(string[] args)
{
string[] data;
bool b = GetStringArr(out data);
}
[DllImport("MyData.dll",
CallingConvention = CallingConvention.Cdecl)]
public static extern bool GetStringArr(
[MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_BSTR)]
out string[] strServerList);
}
您可以访问本机DLL的源吗? 如果是这样,您可以在“托管项目”选项中启用非托管调试,然后遍历非托管代码(最好是Debug build)以查看发生了什么。 如果没有其他要求,则可以在调试器选项中启用“异常”,然后进行调试以查看将本地异常抛出到何处。
我建议您将C ++ / CLI项目(程序集)添加到C#解决方案中。 这样一来,您就可以同时编写托管和非托管领域中的代码。 这意味着您的C ++ / CLI代码可以代替创建List<string^>
并向其中添加托管字符串,然后再将其返回给C#。 :-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.