使用Koffi调用mylib.dll的setup函数时无法正确获取输出值求助
问题分析与解决方案
你的代码核心问题在于对wchar_t**类型输出参数的内存分配和读取逻辑错误,以下是具体修正步骤:
1. 错误点拆解
- 函数参数
wchar_t**表示DLL会返回一个指向宽字符串的指针(即DLL内部分配内存后,把指针地址写入你传入的变量),但你用koffi.alloc('wchar_t*', 1024+1)分配了1025个指针大小的内存,完全不符合需求——你只需要分配1个指针大小的空间来存储DLL返回的指针地址。 - 读取输出时,你直接对
wchar_t**类型的缓冲区解码,而正确逻辑是先读取缓冲区里的wchar_t*指针,再解码这个指针指向的宽字符串。
2. 修正方案(两种方式任选)
方式一:使用Koffi的koffi.out简化输出参数处理
这是Koffi推荐的处理输出指针的方式,无需手动分配内存:
const koffi = require('koffi'); const lib = koffi.load('mylib.dll'); // 用koffi.out标记输出参数 const setup = lib.func('setup', 'int', ['const wchar_t *', koffi.out('wchar_t *')]); const inputJson = { "config": { "pass": "123" } } const jsonString = JSON.stringify(inputJson); function stringToWideCharBuffer(str) { const buffer = Buffer.alloc((str.length + 1) * 2); buffer.write(str, 0, 'utf16le'); return buffer; } const jsonConfig = stringToWideCharBuffer(jsonString); // 直接声明变量接收输出指针 let jsonOutPtr = null; const result = setup(jsonConfig, jsonOutPtr); console.log(result); if (result === 0) { // 直接解码指针指向的宽字符串 const outputStr = koffi.decode(jsonOutPtr, 'wchar_t*'); console.log('Output JSON:', outputStr); // 重要:如果DLL用malloc分配内存,必须调用DLL提供的释放函数(比如free_output)避免内存泄漏 // const freeOutput = lib.func('free_output', 'void', ['wchar_t *']); // freeOutput(jsonOutPtr); } else { console.error('setup failed with code:', result); }
方式二:手动处理指针分配与读取
如果你想手动管理内存,按以下步骤修改:
const koffi = require('koffi'); const lib = koffi.load('mylib.dll'); const setup = lib.func('setup', 'int', ['const wchar_t *', 'wchar_t **']); const inputJson = { "config": { "pass": "123" } } const jsonString = JSON.stringify(inputJson); function stringToWideCharBuffer(str) { const buffer = Buffer.alloc((str.length + 1) * 2); buffer.write(str, 0, 'utf16le'); return buffer; } const jsonConfig = stringToWideCharBuffer(jsonString); // 仅分配1个指针大小的内存,用于存储DLL返回的wchar_t*地址 const jsonOutPtrBuf = koffi.alloc('wchar_t*'); const result = setup(jsonConfig, jsonOutPtrBuf); console.log(result); if (result === 0) { // 第一步:读取缓冲区里的wchar_t*指针 const jsonOutPtr = koffi.decode(jsonOutPtrBuf, 'wchar_t*'); // 第二步:解码指针指向的宽字符串 const outputStr = koffi.decode(jsonOutPtr, 'wchar_t*'); console.log('Output JSON:', outputStr); // 同样,记得调用DLL的内存释放函数(如果需要) // const freeOutput = lib.func('free_output', 'void', ['wchar_t *']); // freeOutput(jsonOutPtr); } else { console.error('setup failed with code:', result); }
关键注意事项
- 如果DLL是通过
malloc分配的输出字符串内存,必须调用DLL提供的对应释放函数(比如free_output),否则会造成内存泄漏——不要用Node.js的free或koffi.free,因为DLL和Node.js可能使用不同的内存分配器。 - 确认你的DLL确实是通过
wchar_t**返回字符串,部分DLL可能要求调用者预先分配缓冲区,此时函数参数会包含缓冲区大小(比如int setup(const wchar_t* input, wchar_t* output, size_t buf_size)),这种情况下你需要调整内存分配和函数定义。
内容的提问来源于stack exchange,提问作者hhpr98
相关产品推荐
相关产品推荐

