C++ C++;调用消费应用程序中实现的函数的DLL

C++ C++;调用消费应用程序中实现的函数的DLL,c++,dll,function-pointers,virtual-functions,C++,Dll,Function Pointers,Virtual Functions,如何从DLL函数调用具有复杂返回类型的后实现函数(例如,在消费应用程序中实现的函数指针或虚拟函数) 我尝试了以下方案,但出现了错误 测试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函数调用具有复杂返回类型的后实现函数(例如,在消费应用程序中实现的函数指针或虚拟函数)

我尝试了以下方案,但出现了错误

测试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;
}
消费应用程序的运行方式如下:

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();
}
随后我收到一条错误消息:

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.
我不知道到底发生了什么。当我尝试使用char指针的返回类型时,也发生了错误。char指针将在使用新运算符的应用程序中创建,并将在使用delete[]运算符的DLL函数中释放


有人能解释一下错误发生的原因,并给我提出一些解决方案吗?谢谢大家!

也许您的呼叫约定不匹配。可能字符串test_impl()应该是字符串stdcall test_impl()。

您很可能正在链接不同版本的C运行库,从而阻止了共享堆的使用。确保应用程序和dll都使用相同的C运行时库“风格”(动态或静态)链接-如果不确定要选择哪一个,请将它们都设置为动态


./p>在EXE和DLL之间传递C++对象并不是一个好主意,更重要的是,如果对象是基于模板类和/或内联方法,那么如果对象在内部分配内存,则更是如此。如果您的应用程序和库之间需要这种接口,那么我建议您将dll切换到静态库,这样可以避免大多数问题

如果需要将dll保持为dll,那么我建议您只在exe和dll之间传递本机类型。在您的示例中,将
string
的所有用法切换为
char*
可能会解决崩溃问题


另外,请听取Jim Rhodes的建议,并声明一个明确的调用约定,即使您发现在这种情况下这不是问题所在。

您真正想要导出/导入的内容尚不清楚。您可以从main.cpp导出test_impl,并从test.cpp导入main.cpp中的launch

无论如何,您可能还应该导出类(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(); } 
//test.cpp
类型定义declspec(dllimport)标准::字符串(*测试)(无效);
外部declspec(dllexport)测试;
测试uu测试=0;
extern_uudeclspec(dllexport)int launch(){std::string a=uu test();

std::难道我不相信你可以在应用程序中新建并在dll中删除。这会导致堆损坏。是的,我也相信这就是它不起作用的原因。我真的不知道如何实现我描述的方案(即调用应用程序中实现的函数)。感谢您的关注,但似乎无法解决此问题。我尝试修改:Test.h:typedef string(u stdcall*Test)(void);Main.cpp:string u stdcall Test_impl()…错误仍然发生。我尝试了您的代码,但是错误仍然是一样的:
这可能是由于堆损坏,这表明TestRun.exe或它加载的任何DLL中存在错误。
我认为@Miguel可能是对的,我将代码编译到一个静态库中,它可以工作。我的主要目的是隐藏代码并让别人知道我真的不在乎它是一个静态库还是一个DLL。尽管如此,我还是想找出当它被编译成DLL时出错的原因。