1

我尝试了两个星期来创建一个 DLL,我可以向其传递字符串并取回字符串。但仍然没有成功。

我在 Dev-C++(TDM-GCC 4.9.2) 和 Visual Studio 社区 2015 上尝试了这个。我对此进行了很多搜索,并尝试了我找到的几乎所有示例代码,但没有成功。

我必须将此 DLL 与MetaTrader 终端 4一起使用。
这是我使用的一个示例代码。此代码编译成功,但是当我从 MT4string发送到此代码时,我收到访问冲突错误。

#ifndef MYLIB_HPP
#define MYLIB_HPP

#include <string>

#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllimport) 
#else
#define MYLIB_API __declspec(dllexport) 
#endif
bool MYLIB_API test(const std::string& str);
#endif

bool MYLIB_API MyTest(const std::string& str)
{
    return (str == "Hi There");
}
4

3 回答 3

2

如果您确实string在 DLL 和另一个可执行文件之间共享 C++,则两者都需要使用相同的工具链进行编译。这是因为std::string仅在标题中定义。因此,如果 DLL 和可执行文件使用不同的string标头,它们很可能是二进制不兼容的。

如果您想确保使用不同的工具链可以正常工作,请坚持使用以 NULL 结尾的 C 字符串。

于 2016-12-10T10:42:05.467 回答
1

您刚刚体验了 MQL4 技巧之一,
MQL4string不是一个string ,而是一个struct因此#import在 MQL4 方面将使 MT4 注入它,不符合您的 DLL C 端期望并且访问冲突错误很简单,因为您的 C 端代码试图访问 MQL4 区域...


设计 API/DLL 的第一条规则:非常仔细地阅读文档。

是的,有人可能会反对,说 MQL4 文档有点难以理解,但因此比规则#1 还要多一倍,请非常、非常、非常仔细地阅读文档,因为一些重要的设计事实几乎隐藏在一些不太可预测的章节中,或者在 ENUM 表、编译器指令、pragma-s 旁注等的解释中的某处。


第二条规则:设计API/DLL接口,以便能够顺利集成

MQL4 在某处更改了关于 Build 670+ 的规则。好消息是,MetaQuotes 已经宣布,他们不会对 MT4 的进一步开发进行进一步投资,因此 DLL/API 集成的 MT4 方面有望停止进一步蔓延。

鉴于您的陈述,即您设计 DLL/API,请尝试设计面向未来的规范——使用uchar[]-s 块而不是“解释”-sensitive ,通过引用string传递输入和输出并仅返回某种形式的和您的努力将产生干净的代码,在 3rd 方语言包装器之间具有更好的可移植性,并且还将最大限度地减少您的进一步维护成本。int aReturnCODE = myDLL_FUNC( byRefParA, byRefParB, byRefRESULT );

于 2016-12-13T04:52:33.437 回答
0

最有可能的是,您的代码和您要链接的代码已使用不同的 ABI 编译std::string,即库使用的字符串与您正在编译的字符串具有不同的内存布局(和sizeof)。

在链接 hdf5 库并使用 gcc 时,我曾经遇到过这个问题。在这种情况下,可以通过恢复到以前的 ABI 来解决问题,如此所述。

但是,当没有这样的解决方案时,clang 也出现了问题。因此,为了使这一切正常工作,我必须避免在对使用std::string不同 ABI 编译的库(在我的情况下为 hdf5)的任何调用中使用,而是使用 hdf5 接口使用const char*.

于 2016-12-10T10:57:01.813 回答