如何使用DLL函数中的复杂返回类型调用后实现函数(例如,在使用应用程序中实现的函数指针或虚函数)?
我尝试了以下方案,但遇到了错误。
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;
}
消费应用程序如下:
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指针时会出现错误,该指针将使用new运算符在使用应用程序中创建,并且将使用delete []运算符在DLL函数中释放。
有人可以解释错误发生的原因,并建议我解决这个问题吗?谢谢!
答案 0 :(得分:1)
在exe和dll之间传递C ++对象实际上并不是一个好主意,如果对象基于模板类和/或具有内联方法,则更是如此,如果对象在内部分配内存,则更是如此。如果您需要在应用程序和库之间使用这种接口,那么我建议您将dll切换到静态库,然后避免大多数问题。
如果你需要将dll保持为dll,那么我建议你只在exe和dll之间传递本机类型。在您的示例中,将string
的所有用法切换为char*
可能会解决崩溃问题。
同样从Jim Rhodes那里得到很好的建议并声明一个明确的调用约定,即使你发现在这种情况下这不是问题。
答案 1 :(得分:0)
也许你的调用约定不匹配。也许字符串test_impl()应该是字符串__stdcall test_impl()。
答案 2 :(得分:0)
您很可能正在使用不同版本的C运行时库进行链接,从而阻止了共享堆的使用。确保app和dll都与C运行时库的相同'flavor'(动态或静态)链接 - 如果您不确定要选择哪一个,请将它们设置为动态。
另见Strange problems with new/delete in an app that uses my DLL。
答案 3 :(得分:0)
您真正想要导出/导入的内容尚不清楚。您从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(); }
但请检查两个项目是否使用相同的模型(/ MTd,/ Mt)进行编译