让结构
struct MyDataStructure
{
int a;
int b;
string c;
};
让dll公开的接口中有一个函数。
class IDllInterface
{
public:
void getData(MyDataStructure&) = 0;
};
从加载dll的客户端exe,以下代码是否安全?
...
IDllInterface* dll = DllFactory::getInterface(); // Imagine this exists
MyDataStructure data;
dll->getData(data);
...
当然,假设客户端和dll都知道MyDataStructure。另外根据我的理解,由于代码是针对dll和exe单独编译的,因此对于差异编译器/编译器版本,MyDataStructure可能不同。我的理解是否正确。
如果是这样,在使用不同的编译器/编译器版本时,如何安全地在dll边界之间传递数据。
答案 0 :(得分:1)
您可以使用“协议”方法。为此,您可以使用内存缓冲区来传输数据,双方只需要就缓冲区布局达成一致。
协议协议可能类似于:
对于两个整数的特殊情况,前8个字节有整数,之后就是字符串数据。
#define MAX_STRING_SIZE_I_NEED 128
// 8 bytes for ints.
#define DATA_SIZE (MAX_STRING_SIZE_I_NEED + 8)
char xferBuf[DATA_SIZE];
所以Dll设置int等,例如
void GetData(void* p);
// "int" is whatever type is known to use 4 bytes
(int*) p = intA_ValueImSending;
(int*) (p + 4) = intB_ValueImSending;
strcpy((char*) (p + 8), stringBuf_ImSending);
在接收端,将缓冲的值放在struct中是很容易的:
char buf[DATA_SIZE];
void* p =(void*) buf;
theDll.GetData(p);
theStrcuctInstance.intA = *(int*) p;
theStrcuctInstance.intB = *(int*) (p + 4);
...
如果你想要你甚至可以就每个整数字节的字节顺序达成一致,并设置缓冲区中每个整数的4个字节中的每个字节 - 但你可能不需要达到那个程度。
为了更一般的目的,双方可以就缓冲区中的“标记”达成一致。缓冲区看起来像这样:
<marker>
<data>
<marker>
<data>
<marker>
<data>
...
Marker:第1个字节表示数据类型,第2个字节表示长度(非常像网络协议)。
答案 1 :(得分:1)
如果要在COM中传递字符串,通常需要使用COM BSTR对象。您可以使用SysAllocString
创建一个。这被定义为在编译器,版本,语言等之间保持中立。与流行的看法相反,COM直接支持int
类型 - 但从它的角度来看,int
始终是32位类型。如果你想要一个64位整数,那就是Hyper
,用COM说话。
当然,您可以使用您的连接双方都知道/理解/同意的其他格式。除非你有非常这样做的理由,否则几乎肯定是一个糟糕的主意。 COM的主要优势之一就是你似乎想要的那种互操作 - 但是发明你自己的字符串形式会大大限制它。
答案 2 :(得分:0)
使用JSON进行通信。
我认为我找到了一种更简单的方法来回答自己的问题。正如@Greg的答案所建议的那样,必须确保数据表示遵循一种协议,例如网络协议。这样可以确保不同二进制组件(此处为exe和dll)之间的对象表示形式无关。如果我们再考虑一下,这就是JSON通过定义简单的对象表示协议解决的相同问题。
所以对我来说,一个简单而强大的解决方案是从exe中的对象构造一个JSON对象,对其进行序列化,以字节为单位跨dll边界传递,并在dll中反序列化。 dll和exe之间唯一的协议是它们都使用相同的字符串编码(例如UTF-8)。
https://en.wikibooks.org/wiki/JsonCpp
一个人可以使用上面的Jsoncpp库。默认情况下,字符串在Jsoncpp库中由UTF-8编码,因此也很方便:-)