C++ DLL calling a function implemented in the consuming application

Refresh

December 2018

Views

329 time

2

How to call a post-implemented function (e.g., function pointers or virtual functions implemented in the consuming application) with a complex return type from a DLL function?

I tried the following scheme but got errors.

Test.h:

#ifdef _DLL_IMPL
#define DLL_EXPORT __declspec(dllexport)  
#else  
#define DLL_EXPORT __declspec(dllimport)  
#endif
typedef string (*test)(void);
extern DLL_EXPORT test __test;
DLL_EXPORT int launch();

Test.cpp:

#define _DLL_IMPL
#include "Test.h"
test __test = 0;
int launch()
{
    string a = __test();
    return 0;
}

And the consuming application goes like:

Main.cpp:

#include "Test.h"
#pragma comment(lib, "Test.lib")
string test_impl()
{
    string a = "test";
    return a;
}
int main(int args, char** argv)
{
    __test = &test_impl;
    return launch();
}

And I got a subsequent error message:

Windows has triggered a breakpoint in TestRun.exe.

This may be due to a corruption of the heap, which indicates a bug in
TestRun.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while TestRun.exe has focus.

The output window may have more diagnostic information.

I don't know what exactly was going on. Error also occurred when I tried a return type of a char pointer, which would be created in the consuming application using a new operator and would be freed in a DLL function using a delete[] operator.

Can someone explain the reason why the error happens and suggest me some solution to this scheme? Thank you!

4 answers

0

То, что вы действительно хотите экспортировать / импортировать не ясно. Вы экспортировать test_impl из main.cpp и запуска импорта в main.cpp из test.cpp

Во всяком случае, вероятно, вы должны экспортировать также классы (Std :: string).

Следующий код работает отлично:

//test.cpp
typedef __declspec(dllimport)    std::string        (*test)(void); 

    extern __declspec(dllexport)  test __test;

    test __test = 0; 

extern __declspec(dllexport)    int launch() {      std::string a = __test();     
std::cout << a << std::endl ; 
return 0; } 

// main.cpp 
typedef __declspec(dllexport)    std::string        (*test)(void); 
extern __declspec(dllimport)  test __test;
extern __declspec(dllimport)  test __test;

__declspec(dllimport)  int launch(); 

__declspec(dllexport) 
std::string test_impl() {  
    std::string a = "test";   
    return a; } 

int main(int args, char** argv) {  
    __test = &test_impl;    
    return launch(); } 

Проверьте, однако, что оба проекта собраны с одной и той же модели (/ MTd, / Mt)

0

Вы очень вероятно, связывают с различными версиями библиотек C во время выполнения, предотвращающих совместное использование кучи. Убедитесь, что оба приложения и библиотеки DLL связаны с тем же «ароматом» (динамическим или статическим) из библиотеки времени выполнения C - если вы не уверены, какой из них выбрать, установить их обоих в динамический.

Смотрите также странные проблемы с новым / удалить в приложении , которое использует мой DLL .

1

Передача C ++ объекты между EXE и DLL действительно не очень хорошая идея, тем более, если объект на основе шаблона класса и / или имеет встраиваемыми методы, и даже более того, если объект выделяет память внутри. Если вам нужен такой интерфейс между приложением и библиотекой, то я рекомендую вам переключить DLL в статическую библиотеку, то вам избежать большинства проблем.

Если вам необходимо сохранить DLL как библиотеки DLL, то я рекомендую вам только передать собственные типы между EXE и DLL. В вашем примере, переключение всех обычаев , stringчтобы char*, скорее всего , обратиться к аварии.

Кроме того, принять хороший совет от Джима Родса и объявить явное соглашение о вызовах, даже если вы обнаружили, что это не проблема в данном конкретном случае.

0

Возможно, у вас есть вызывающее несоответствие конвенции. Может быть строка test_impl () должна быть строка __stdcall test_impl ().