从dll返回多个string

我们正在讨论什么是从一个dll函数返回多个string的好方法。 目前我们有8个string,但会有更多。 为了简单,我现在认为所有的string将具有相同的长度

extern "C" int DLLNAME_ _stdcall GetResult(TestResults* testResults); 

哪里

 struct TestResults { int stringLengths; char* string1; char* string2; char* string3; char* string4; ... }; 

或第二个选项:在哪里

 struct TestResults { int stringLengths; char string1[64]; char string2[64]; char string3[64]; char string4[64]; ... }; 

第三个选项:extern“C”int DLLNAME_ _stdcall GetResult(int stringLengths,char * string1,char * string2,char * string3,…);

该DLL将通过串行线进行通信,并检索将填充到string中的信息。 记忆需要分配的地方是开放讨论的,可以成为答案的一部分。

背景是,我们有一个VB6应用程序团队喜欢第二种方法和一个喜欢第一种方法的C ++ / C#团队。 最后的方法看起来适合这两个队,但看起来有点奇怪,有这么多的参数。

也许有更多的select。 Windows下常见的做法是什么? 来自Windows API的任何示例或参数都可以select其中一个?

编辑:string有名字,姓氏,电子邮件的意思。 我们目前有八个,但是将来我们可能会增加一个地址作为例子。 一个数组不是正确的select,但是从原始的上下文来看,这是不清楚的。

最好的方法可能是使用存储BSTR字符串的安全数组

VB和C#都非常了解安全数组:在C#中,安全的BSTR字符串数组会自动转换为string[]数组。

在C ++端,可以使用ATL::CComSafeArray辅助类来简化安全的数组编程。

您将在本MSDN杂志文章中找到有趣的内容 (特别是看看生成字符串安全数组的段落)。


从前面提到的文章:在C ++端,你可以实现一个C接口 DLL,导出一个这样的函数:

 extern "C" HRESULT MyDllGetStrings(/* [out] */ SAFEARRAY** ppsa) { try { // Create a SAFEARRAY containing 'count' BSTR strings CComSafeArray<BSTR> sa(count); for (LONG i = 0; i < count; i++) { // Use ATL::CComBSTR to safely wrap BSTR strings in C++ CComBSTR bstr = /* your string, may build from std::wstring or CString */ ; // Move the the BSTR string into the safe array HRESULT hr = sa.SetAt(i, bstr.Detach(), FALSE); if (FAILED(hr)) { // Error... return hr; } } // Return ("move") the safe array to the caller // as an output parameter (SAFEARRAY **ppsa) *ppsa = sa.Detach(); } catch (const CAtlException& e) { // Convert ATL exceptions to HRESULTs return e; } // All right return S_OK; } 

在C#端,你可以使用这个PInvoke声明:

 [DllImport("MyDll.dll", PreserveSig = false)] public static extern void MyDllGetStrings( [Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] result); 

当你声明你的函数为extern "C"我想你不能使用std::vector<std::string>作为返回类型。

另一种可能性是:

 struct String { int size; /* size of string */ const char* str; /* actual string */ } struct TestResults { int size; /* number of strings */ String* arr; /* pointer to an array of String */ }; 

然后和以前一样:

 extern "C" int DLLNAME_ _stdcall GetResult(TestResults* testResults); 

因此,您可以灵活地根据需要返回尽可能多的字符串。 此外循环通过您的TestResults很容易。

编辑#1:如评论中所说:使用BSTR 。 所以你的结构看起来像这样:

 struct TestResults { int size; /* number of strings */ BSTR* arr; /* pointer to an array of BSTR */ }; 

一个BSTR将被分配 : BSTR MyBstr = SysAllocString(L"I am a happy BSTR"); 。 这个分配也设置了包含字符串长度的成员。 你必须释放分配的内存: SysFreeString(MyBstr); 。 你也需要分配整个数组BSTR*