P / Invoke呼叫失败

时间:2014-01-31 17:50:45

标签: c# c++ struct pinvoke

我在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#中,我有一个'mirror'结构声明:

[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#app中的以下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#app都编译为x86或x64),我得到了不同的结果:

  • 在x86模式下,调用返回,但结构中有“无意义”值,字符串全为空,
  • 在x64模式下,调用抛出NullPointerException。

我的期望是我做错了编组字符串,我需要为字符指定'宽模式',但我不知道如何(或者如果这是正确的选项)。< / p>

提前谢谢你。

2 个答案:

答案 0 :(得分:2)

C ++类型与C#不兼容,除非它们包含在托管C ++中。并且您正在使用无法编组到.NET中的std::wstring

要成功互操作,您需要使用wchar_t[]whar_t*并告诉C#现在编组。

答案 1 :(得分:0)

我不知道你的宏在做什么,但这只有在你的c ++类型为POD时才有效。 c ++ 11具有扩展的POD感,但我认为您无论如何都不符合扩展标准。否则你不能保证布局。如果要将c ++类导出到C#,我建议你使用c ++ \ cli。你的stuct中也定义了wstring,绝对不是POD。当您使用DLLImport时,只考虑C构造,否则您将遇到不好的时间。