将 javascript 字符串传递给 std::string 打印垃圾值

Posted

技术标签:

【中文标题】将 javascript 字符串传递给 std::string 打印垃圾值【英文标题】:Passing javascript string to std::string prints garbage values 【发布时间】:2021-02-14 05:04:12 【问题描述】:

我正在使用 C++ 和 ElectronJS。我正在尝试使用 ElectronJSnode-ffijavascript 字符串传递给 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::stringstd::string 是 C++ 的东西,只有 C++ 知道,即使这样,当使用不同的 C++ 编译器或编译器选项时,也可以有不同的内部结构。此外,std::string 具有内部内存管理,这意味着 std::string 在一个模块中使用的堆需要与调用模块中使用的堆相同。另外,std::string 是临时的——你也有范围的问题。寻找另一种在语言之间安全传递字符数据的方法。 "使用 ElectronJSnode-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 打印垃圾值的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Python 字符串传递给 C++(外部 C)函数

如何将非可变参数值传递给 fmt::format?

将结构传递给 C#

是否可以使用 emscripten 使用 Javascript 从 C++ 打印字符串?

传递给第三方 API 时的 C++ const std:string& 安全性

如何将此 std::function 传递给 std::async