如何将C++dll中的unicode字符串/wstring/CStringW返回到InstallScript
How do I return a unicode string / wstring / CStringW from a C++ dll to InstallScript?
我使用的是InstallShield 2013 Premium。我在Visual Studio 2010中创建了一个C++dll,以提供一些单独使用InstallScript无法实现的功能。我的C++函数需要在完成大量工作后向InstallScript返回一个小字符串(用户名(来获得这个值。
在整个C++中,我使用CStringW来表示我的字符串。理想情况下,我希望将其返回为Unicode,但如果这是我唯一的选择,我对ANSI感到满意。我尝试过许多CStringW、std::wstring、std::string、LPCTSTR、LPSTR、char*。。。我尝试了直接返回,并尝试通过引用返回。什么都不管用!
有时dll函数挂起,有时抛出异常,最多返回带有非打印字符的垃圾值。这方面的官方文件似乎不准确(对我来说不起作用!(。广泛的谷歌搜索和搜索Flexera董事会从其他人那里得到了解决同样荒谬问题的"解决方案",但这些对我来说也不管用。。。
直到最后我才尝试,因为我认为你可以很容易地在dll和InstallScript之间传递字符串是理所当然的。回想起来,我应该从两者之间的接口开始,然后开发dll功能。
感谢大家的帮助!不过我终于自己想明白了。然而,这个解决方案有多个方面,我在其他地方没有发现记录或建议。
要点
1( 从C++返回WCHAR*
2( 在InstallScript原型中使用WSTRING作为相应的返回类型
3( 将其返回到InstallScript中的常规STRING变量中,并将其视为任何其他
4( 将WCHAR*在C++dll中指向的值保留在静态变量中,否则它显然会被删除,指针将变为无效
如果你已经走到了同一条船上,我可能不需要提供每一个细节,但这里有一大块示例代码可以帮助你:
Visual Studio Def文件
LIBRARY MyIsDllHelper
EXPORTS
getSomeStringW @1
C++标头
#ifdef MYISDLLHELPER_EXPORTS
#define MYISDLLHELPER_API __declspec(dllexport)
#else
#define MYISDLLHELPER_API __declspec(dllimport)
#endif
#include <stdexcept>
#include <atlstr.h>
namespace MyIsDllHelper
{
class MyIsDllHelper
{
public:
static MYISDLLHELPER_API WCHAR * getSomeStringW();
};
}
C++源
#include "stdafx.h"
#include "MyIsDllHelper.h"
static CStringW someStringRetained;
CStringW getTheString()
{
CStringW s;
// do whatever...
return s;
}
WCHAR * MyIsDllHelper::MyIsDllHelper::getSomeStringW()
{
someStringRetained = getTheString();
return someStringRetained.GetBuffer( someStringRetained.GetLength() ) + L' ';
}
InstallScript
#define HELPER_DLL_FILE_NAME "MyIsDllHelper.dll"
prototype WSTRING MyIsDllHelper.getSomeStringW();
function DoSomething( hMSI )
STRING svSomeString;
STRING svDllPath;
begin
// Find the .dll file path. (A custom function)
GetSupportFilePath( HELPER_DLL_FILE_NAME, TRUE, svDllPath );
// Load the .dll file into memory.
if( UseDLL( svDllPath ) != 0 ) then
MessageBox ("Could not load dll: " + svDllPath, SEVERE );
abort;
endif;
// Get the string from the dll
try
svSomeString = MyIsDllHelper.getSomeStringW();
catch
MessageBox( "Could not execute dll function: MyIsDllHelper.getSomeStringW", SEVERE );
abort;
endcatch;
// Remove the .dll file from memory.
if( UnUseDLL( svDllPath ) < 0 ) then
MessageBox ("Could not unload dll: " + svDllPath, SEVERE );
abort;
endif;
// Use the string
MessageBox( "svSomeString: [" + svSomeString + "]", INFORMATION );
end;
当您可以让您的接口使用C方法而不是C++方法时,您将处于最佳状态。匹配GetEnvironmentVariable等函数的接口,在该接口中,函数接受指向缓冲区的指针(为了正确起见,还接受该缓冲区的大小(,然后写入该缓冲区。只要您可以完成从CString到缓冲区的StringCchCopy之类的操作,那么您的大部分实现就不必更改。
由于您特别提到CStringW和其他Unicode字符串类型,我建议选择LPWSTR
(而不是LPTSTR
(作为接口类型。
然后剩下的就是声明这个供InstallScript使用。这意味着原型应该使用WSTRING和BYREF。如果函数接口与GetEnvironmentVariableW相同,那么原型应该如下所示:
prototype MyFunc(WSTRING, BYREF WSTRING, NUMBER);
您可以使用字符串,但我想问题出在编码上。
看看这里:https://adventuresinscm.wordpress.com/2014/01/12/unicode-files-and-installshield/
- Ctypes wstring通过引用传递
- 在C++中将变量 wstring 分配给 Char 数组
- 将日语 wstring 转换为 std::string
- 使用 memcpy 将矢量数据复制到 wstring 的正确方法
- 使用 CStringW/CStringA 和 CT2W/CT2A 转换字符串有什么区别?
- -fshort-wchar 和 std::wstring - 分段错误
- 输出 c++ 窗口 wstring 日志在终端中正确
- 从 uint32_t 转换为 wchar_t 并存储在 wstring 中时出现访问冲突
- 如何将std::wstring转换为char const[]
- 将utf16宽std::wstring转换为utf8窄std::string以获得罕见字符时出现问题
- 找不到 std::wstring 中存在的wchar_t
- 将 char* argv[] 转换为 wstring
- 将 std::string 转换为具有特殊字符的 FString (TCHAR / wstring)
- 在 C++ 中将 utf8 wstring 转换为窗口中的字符串
- 使用 ReadProcessMemory() 将未知大小的字符数组或字符串读入 wstring 中
- 从字符的 ASCII 代码点到 wstring
- 将整数附加到 std::wstring 会给出错误
- boost库的哪一部分使cout能够打印wstring以及如何打印?
- 如何将 wstring 转换为 wchar_t*?C++
- 如何将C++dll中的unicode字符串/wstring/CStringW返回到InstallScript