我试图调用C ++ dll中声明为__declspec(dllexport)的方法在C#中使用,但我不知道如何从C ++返回字符串值以及如何使用DllImport声明签名在C#。
C ++代码“VNVAPI.dll”
__declspec(dllexport) char * GetGpuName(int phyGPUid)
{
CNvidia * pInstance = CNvidia::GetInstance();
char szName[512]={0};
pInstance->GetGpuName(phyGPUid,szName,512);
return szName;
}
C#方法签名:
[DllImport("VNVAPI.dll")]
public static extern char GetGpuName(int phyGPUid);
生成错误:
调用PInvoke函数 '核心!Core.Hardware.IO.NVAPI :: GetGpuName' 堆栈不平衡。这是 可能是因为管理的PInvoke 签名与非托管不匹配 目标签名。检查一下 调用约定和参数 PInvoke签名与目标匹配 非托管签名。
感谢。
答案 0 :(得分:2)
正如其他人所指出的那样,您需要在P / Invoke中指定C调用约定,并使用托管端的字符串来封送空终止的char *。
但是,您应该重新调整C ++例程以将char *作为输入参数以及缓冲区长度参数。然后,您可以在本机代码中写入此缓冲区。这避免了当前问题,即当前您拥有代码的数据是从堆栈返回的,当然,当函数返回时,它会被展开。
使用static的建议会使这个内存全局化,从而避免堆栈展开问题,但代价是线程安全。是的,它可能适用于这个用例,但这是一个不好的习惯。
答案 1 :(得分:0)
错误消息可能令人困惑。
不详细说明,试试这个:
static char szName[512]={0};
如果仍然出现错误,则需要在DllImport
属性中指定调用约定。
编辑:
还为C#方法声明生成返回类型string
。
答案 2 :(得分:0)
错误消息建议检查调用约定。我怀疑该函数正在使用C调用约定,这将解释不平衡堆栈。我建议您在DllImport
属性中指定调用约定(如@leppi建议的那样)。像这样:
[DllImport("VNVAPI.dll", CallingConvention=CallingConvention.Cdecl)]
根据Strings samples,返回值应为string
:
static extern string GetGpuName(int phyGPUid);