我正在开发一个 Thunderbird 扩展,它将通过 C++/CLR 中介调用现有的 C# 代码。我遇到了一个可以仅使用 C++/CLR DLL 或直接 C DLL 复制的障碍。
我的功能是
__declspec(dllexport)char* strTest2()
{
char *p = "Hello World";
char buffer[200];
char *q = buffer;
strcpy_s(q,200,p);
return p;
}
如果我返回 p,我会返回“Hello World”。如果我返回 q,我会得到垃圾或挂起。在调试器中检查 p 和 q 表明它们都包含相同的数据。
我正在使用这个 js 调用函数;
Components.utils.import("resource://gre/modules/ctypes.jsm");
var lib = ctypes.open("<path to DLL>");
var getStr = lib.declare("strTest2",
ctypes.default_abi,
ctypes.char.ptr);
var str = getStr();
alert(str.readStringReplaceMalformed());
lib.close();
在 Mozilla 调试器中,str 被标识为 CData 类型的对象,并且深入挖掘表明它在每种情况下都包含一个字符串,尽管我无法看到该字符串是什么。
js-ctype 的文档说,如果 CData 直接引用了某些内容,那么它将保持活动状态。但在我看来,这并没有正确发生。
如果我指定一个大的“静态”缓冲区,例如
char *r = "\0....\0";
然后使用 strcpy_s 将文本复制到该缓冲区并返回 r 然后字符串通过。如果我使用的是直接 C 的 DLL 项目。但如果我尝试使用 C++/CLR DLL 项目,我需要使用它才能获取现有的 C# 代码,然后尝试写入硬编码缓冲区导致程序坠毁。
所以我看到了三种前进的方式;
- 让运行时创建的字符串在从 C++/CLR 切换回 js-ctypes 时保持不变,
- 获取 C++/CLR 以允许我更改静态缓冲区 - 而不会导致多个实例出现问题,
- 让 JS 提供 C++/CLR 可以填充的缓冲区。
有谁知道如何让其中一个工作?