将 javascript 字符串传递给 std::string 打印垃圾值
Posted
技术标签:
【中文标题】将 javascript 字符串传递给 std::string 打印垃圾值【英文标题】:Passing javascript string to std::string prints garbage values 【发布时间】:2021-02-14 05:04:12 【问题描述】:我正在使用 C++ 和 ElectronJS。我正在尝试使用 ElectronJS 和 node-ffi 将 javascript 字符串传递给 c++ dll。除了GetString
之外,其余公开的功能都可以正常工作。
Javascript 代码:
window.onload = function ()
try
// Call *.dll with ffi
let ffi = require('ffi-napi');
// Create funtions
window.Dll = ffi.Library(".//dll//BasicMathDll.dll",
'add': ['float', ['float', 'float']],
"subtract": ["float", ["float", "float"]],
"multiply": ["float", ["float", "float"]],
"divide": ["float", ["float", "float"]],
"GetString": ["string",["string"]]
)
console.log("DLL was loaded correctly.");
// Call C++ function Hello
//document.getElementById('hello').innerhtml = Dll.Hello()
catch (error)
console.error('ffi.Library', error);
document.getElementById('result').value = error;
包装器.cpp
std::string GetString(std::string a)
FILE* fp;
fp = fopen("a.txt", "w+");
fprintf(fp, a.c_str());
fclose(fp);
return "The quick brown fox jumps over the lazy dog.";
包装器.h
#pragma once
#ifdef BASICMATHDLL_EXPORTS
#define BASICMATHDLL_API __declspec (dllexport)
#else
#define
#define BASICMATHDLL_API __declspec (dllimport)
#endif
#if defined(WIN32) || defined(_WIN32)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
#ifdef __cplusplus
extern "C"
#endif
typedef struct CWrapper
void* cObject;
CWrapper_T;
CWrapper_T *create();
void destroy(CWrapper_T*);
float CheckTask(CWrapper_T* mObject, float x, float y, char mOperator);
EXPORT float add(float x, float y);
EXPORT float subtract(float x, float y);
EXPORT float multiply(float x, float y);
EXPORT float divide(float x, float y);
EXPORT std::string GetString(std::string);
#ifdef __cplusplus
#endif
我这样调用暴露的 dll 函数:
function GetStr()
// Call C++ function GetString
document.getElementById('string').innerHTML = window.Dll.GetString("Lorem ipsum dolor.");
生成的文本文件 (a.txt) 包含:øã«~SSäã
我认为 javascript 字符串和 c++ std::string 之间的字符编码有问题,这超出了我的知识范围。有人有想法吗?
【问题讨论】:
永远不必同时使用 JavaScript 和 C++,您不应该跨模块边界传递对象,例如std::string
。 std::string
是 C++ 的东西,只有 C++ 知道,即使这样,当使用不同的 C++ 编译器或编译器选项时,也可以有不同的内部结构。此外,std::string
具有内部内存管理,这意味着 std::string
在一个模块中使用的堆需要与调用模块中使用的堆相同。另外,std::string
是临时的——你也有范围的问题。寻找另一种在语言之间安全传递字符数据的方法。
"使用 ElectronJS 和 node-ffi 将 Javascript 字符串传递给 c++ dll。" -- 什么是这两个的文档必须说明接收端用于字符串的格式? (令人怀疑的是,格式不仅是 C++ 特定的,而且是 C++ 编译器特定的,就像 std::string
一样。)
@PaulMcKenzie 也许找到另一种方法很好。即使在我的代码中,由于 ABI 问题,我也将一些 C++ 代码包装到 C 代码中。莫非差距也在这里。
@JaMiT 我需要深入挖掘。我还没有找到任何类似的特定文档。我会进一步检查。 :)
【参考方案1】:
我尝试了 C 样式字符串,它是 const char*
,而不是 C++ std::string
,效果很好。
以下是我所做的小调整。
包装器.h
EXPORT const char* GetString(const char*);
包装器.cpp
const char* GetString(const char* a)
FILE* fp;
fp = fopen("a.txt", "w+");
fprintf(fp, a);
fclose(fp);
return "The quick brown fox jumps over the lazy dog.";
现在我的a.txt
文件具有从 JS 传递的正确值。
【讨论】:
以上是关于将 javascript 字符串传递给 std::string 打印垃圾值的主要内容,如果未能解决你的问题,请参考以下文章
是否可以使用 emscripten 使用 Javascript 从 C++ 打印字符串?