2014-12-03 4 views
1

У меня есть сторонний DLL, и я должен использовать его функции в коде C++/CLI. Я пытаюсь DllImport это, но я получаю сообщение об ошибке:Функция Dllimport, которая возвращает struct

ошибка C33385: «msp_FormatMessage»: функция, которая имеет DllImport пользовательский attribite не может вернуть экземпляр класса

В C# эта проблема может быть решена используя StructLayout, но я не могу найти способ решить эту проблему в C++/CLI.

Определение функции: определение

[DllImport("drtl3.dll", EntryPoint = "msp_FormatMessage")] 
extern "C++" msp_Message msp_FormatMessage(msp_Message* buffer, char type, char RT, char SA, char RTR_MC, unsigned short SAR_MCD, char dataWordCount, unsigned short data[], unsigned int bccw); 

Struct:

typedef struct { 
     msp_WORD type; 
     msp_WORD dataWordCount; 
     msp_WORD bccw; 
     msp_WORD CmdWord1; 
     msp_WORD CmdWord2; 
     msp_WORD Data[32]; 
     msp_WORD StatusWord1; 
     msp_WORD StatusWord2; 
     msp_WORD loopback; 
     msp_WORD bsw; 
     msp_WORD timetag; 
     msp_BYTE present; 
     msp_BYTE transmit; 
     msp_BYTE check; 
     msp_BYTE role; 
} msp_Message; 
+0

Вы должны пометить вопросы 'C++/CLI' как таковые, многие люди, которые смотрят вокруг тега' C++ ', даже не знают, что он существует, поэтому вы должны быть явным об этом при запросе – PeterT

+0

. Вы уверены, что результат возвращаются напрямую, а не как указатель? – svick

+0

[Единственное 'msp_FormatMessage', которое я мог найти] (http://www.module.ru/upload/files/2604_rtl2gsw.pdf#page=47) делает именно это:' msp_Message * msp_FormatMessage ( msp_Message * buffer, msp_BYTE типа, msp_BYTE RT, msp_BYTE SA, msp_BYTE RTR_MC, msp_WORD SAR_MCD, msp_BYTE dataWordCount, msp_WORD * данные, msp_DWORD bccw); ' – svick

ответ

0

Не понимаю проблему .. Показать код. Показать сообщение об ошибке .. Я только что протестировал dllimport со структурами.

Следует отметить, что динамическая загрузка через dlopen и dlsym или с loadlibrary и getprocaddress обычно предпочтительнее. Зачем? Потому что вы не можете «всегда» dllimport. Пример: dllexport с VS2012 не всегда работает с dllimport в g ++. Для того, как экспортируются символы, нет определенного стандарта.

Использование MinGW-г ++ 4.8.1

DLL:

#include <windows.h> 
#include <cstring> 

typedef struct { 
    unsigned short meh; 
    unsigned short bleh; 
    char we[50]; 
} foo; 

extern __declspec(dllexport) foo some_func() 
{ 
    foo f; 
    f.meh = 10; 
    f.bleh = 20; 
    strcpy(f.we, "hello world\0"); 
    return f; 
} 

extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 
{ 
    switch (fdwReason) 
    { 
     case DLL_PROCESS_ATTACH: 
      break; 

     case DLL_PROCESS_DETACH: 
      break; 
    } 
    return TRUE; 
} 

Импортер:

#include <iostream> 

typedef struct { 
    unsigned short meh; 
    unsigned short bleh; 
    char we[50]; 
} foo; 

extern __declspec(dllimport) foo some_func(); 

int main() 
{ 
    foo f = some_func(); 

    std::cout<<f.meh<<" "<<f.bleh<<" "<<f.we<<"\n"; 
    return 0; 
} 

Результат: 10 20 hello world

+0

Да, спрашивающий не достаточно объяснить, что он был на самом деле с помощью' Конкретная конструкция '[DLLImport]' C++/CLI'. Но я думаю, ваш вопрос по-прежнему актуальен, если он хочет, чтобы он работал в чистом C++ – PeterT

+0

Да, вы правы, я использую C++/CLI. Я отредактировал вопрос, чтобы было ясно. – AndrewR

1

Вы должны объявить структуру он возвращается в неуправляемый , это будет работать нормально:

#using <mscorlib.dll> 
using namespace System::Runtime::InteropServices; 

#pragma managed(push, off) 
using msp_WORD = short; 
using msp_BYTE = char; 
typedef struct { 
    msp_WORD type; 
    msp_WORD dataWordCount; 
    msp_WORD bccw; 
    msp_WORD CmdWord1; 
    msp_WORD CmdWord2; 
    msp_WORD Data[32]; 
    msp_WORD StatusWord1; 
    msp_WORD StatusWord2; 
    msp_WORD loopback; 
    msp_WORD bsw; 
    msp_WORD timetag; 
    msp_BYTE present; 
    msp_BYTE transmit; 
    msp_BYTE check; 
    msp_BYTE role; 
} msp_Message; 
#pragma managed(pop) 

[DllImport("drtl3.dll", EntryPoint = "msp_FormatMessage")] 
extern "C++" msp_Message msp_FormatMessage(msp_Message* buffer, char type, char RT, char SA, char RTR_MC, unsigned short SAR_MCD, char dataWordCount, unsigned short data [], unsigned int bccw); 

или, если это не работает, вы всегда можете просто сделать его C путь ++, который также работает на C++/CLI несколько

#include "windows.h" 
#pragma managed(push, off) 
using msp_WORD = short; 
using msp_BYTE = char; 
typedef struct { 
    msp_WORD type; 
    msp_WORD dataWordCount; 
    msp_WORD bccw; 
    msp_WORD CmdWord1; 
    msp_WORD CmdWord2; 
    msp_WORD Data[32]; 
    msp_WORD StatusWord1; 
    msp_WORD StatusWord2; 
    msp_WORD loopback; 
    msp_WORD bsw; 
    msp_WORD timetag; 
    msp_BYTE present; 
    msp_BYTE transmit; 
    msp_BYTE check; 
    msp_BYTE role; 
} msp_Message; 
#pragma managed(pop) 

typedef msp_Message msp_FormatMessage_t(msp_Message* buffer, char type, char RT, char SA, char RTR_MC, unsigned short SAR_MCD, char dataWordCount, unsigned short data [], unsigned int bccw); 

msp_FormatMessage_t *msp_FormatMessage; 
HINSTANCE hDLL; 

int main(array<System::String ^> ^args) 
{ 
    hDLL= LoadLibraryA("drtl3.dll"); 
    msp_FormatMessage = (msp_FormatMessage_t *)GetProcAddress(hDLL,"[email protected]@[email protected]@[email protected]@Z"); 
    msp_Message test = msp_FormatMessage(nullptr, 1, 2, 3, 4, 5, 6, nullptr, 7); 
    Console::Write("type "); 
    Console::WriteLine(test.type); 
    Console::Write("check"); 
    Console::WriteLine(test.check); 

    // std::cout << "type" << test.type << std::endl; 
    //std::cout << "check" << test.check << std::endl; 

    Console::WriteLine(L"Hello World"); 
    return 0; 
} 

Имя [email protected]@[email protected]@[email protected]@Z является то, что вы можете получить, запустив DUMPBIN /EXPORTS drtl3.dll в визуальная студия командной строки. Также может быть ссылка C, которая сделает имя намного меньше.

+1

Нет, он по-прежнему вызывает ту же ошибку – AndrewR

+0

@ maniac98066 Хорошо, я добавил не очень красивый C++ способ сделать это (что также работает с CLI). Я не эксперт CLI, поэтому я не могу вам очень помочь с помощью 'DllImport' – PeterT

Смежные вопросы