P/Invoke调用失败

P/Invoke Calls Failing

本文关键字:失败 调用 Invoke      更新时间:2023-10-16

我在C++中定义了以下结构:

struct GraphicsAdapterDesc {
// ... Just some constructors / operators / destructor here
DEFINE_DEFAULT_CONSTRUCTOR(GraphicsAdapterDesc);
DEFINE_DEFAULT_DESTRUCTOR(GraphicsAdapterDesc);
ALLOW_COPY_ASSIGN_MOVE(GraphicsAdapterDesc);
std::wstring AdapterName;
int32_t AdapterNum;
std::wstring HardwareHash;
int64_t DedicatedVMEM;
int64_t DedicatedSMEM;
int64_t SharedSMEM;
int32_t NumOutputs;
};

在C#中,我有一个这样声明的"镜像"结构:

[StructLayout(LayoutKind.Sequential)]
public struct GraphicsAdapterDesc {
string AdapterName;
int AdapterNum;
string HardwareHash;
long DedicatedVMEM;
long DedicatedSMEM;
long SharedSMEM;
int NumOutputs;
};

我试着非常小心地匹配变量的宽度(尽管我有点不确定该如何处理字符串)。

无论如何,我有以下导出的C方法:

extern "C" __declspec(dllexport) bool GetGraphicsAdapter(int32_t adapterIndex, GraphicsAdapterDesc& outAdapterDesc) {
outAdapterDesc = RENDER_COMPONENT.GetGraphicsAdapter(adapterIndex);
return true;
}

并且,我的C#应用程序中的以下extern方法:

[DllImport(InteropUtils.RUNTIME_DLL, EntryPoint = "GetGraphicsAdapter", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool _GetGraphicsAdapter(int adapterIndex, out GraphicsAdapterDesc adapterDesc);

然而,当我调用它时,它不起作用。我会得到不同的结果,这取决于我是否在x64或x86模式下编译(C++DLL和C#应用程序都编译为x86或x64):

  • 在x86模式下,调用返回,但结构中有"无意义"值,并且字符串都为null
  • 在x64模式下,该调用引发NullPointerException

我的期望是我在编组字符串时做了一些错误的事情,我需要为字符指定"宽模式",但我不知道如何(或者这是否是正确的选项)。

提前谢谢。

C++类型与C#不兼容,除非它们被封装在托管C++中。而您使用的是无法封送至.NET.的std::wstring

要想成功地互操作,您需要使用wchar_t[]whar_t*,并告诉C#立即封送它

我不知道你的宏在做什么,但只有当你的c++类型是POD时,这才会起作用。c++11对POD有一个扩展的感觉,但我认为你无论如何都不符合扩展的标准。否则,无法保证布局。如果您想将c++类导出到c#,我建议您使用c++\cli。此外,您在灰泥中定义了wstring,这些字符串绝对不是POD。当您使用DLLImport时,请只考虑C结构,否则您将度过一段糟糕的时光。

相关文章: