P / Invoke Calls Failing

0

У меня есть следующая структура, определенная в 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;
};

В С# у меня есть "зеркальная" структура, объявленная таким образом:

[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;
}

И следующий метод extern в моем приложении С#:

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

Однако, когда я это называю, это не работает. Я получаю другой результат в зависимости от того, компилирую ли я в режиме x64 или x86 (как DLL C++, так и приложение С# скомпилированы как x86 или x64):

  • В режиме x86 вызов возвращается, но структура имеет "бессмысленные" значения внутри, а строки - все значения null,
  • В режиме x64 вызов вызывает исключение NullPointerException.

Мое ожидание состоит в том, что я делаю что-то неправильно, сортируя строки, и что мне нужно указать "широкий режим" для символов, но я не знаю, как (или если это даже правильный вариант).

Заранее спасибо.

Теги:
struct
pinvoke

2 ответа

2
Лучший ответ

Типы C++ не совместимы с С#, если они не обернуты управляемым C++. и вы используете std::wstring которые не могут быть маршалированы в.NET.

Чтобы успешно взаимодействовать, вам нужно либо использовать wchar_t[] либо whar_t* и сообщить С#, чтобы его whar_t*.

0

Я не знаю, что делают ваши макросы, но это будет работать, только если ваш тип c++ - POD. c++ 11 Имеет расширенное чувство POD, но я не думаю, что вы все равно удовлетворяете расширенным критериям. В противном случае вы не можете гарантировать компоновку. Если вы хотите экспортировать классы c++ в С#, я бы предложил вам использовать c++\cli. Также у вас есть wstring, определенная в вашем столбце, который определенно не POD. Когда вы используете DLLImport, думайте, что C строит только или у вас будет плохое время.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню