V8节点GYP通过参考以更改值

发布于 2025-02-04 02:41:23 字数 594 浏览 3 评论 0 原文

我想通过节点GYP使用C ++实现V8函数,该节点是突变函数参数的。

// c++
using v8::FunctionCallbackInfo;
  using v8::Isolate;
  using v8::Local;
  using v8::Object;
  using v8::Number;
  using v8::String;
  using v8::Value;

  void Method(const FunctionCallbackInfo<Value>&args) {
    Isolate* isolate = args.GetIsolate(); 
    // do something to modify args
    // e.g) args[0] = "changed now!"
  }

这样我就可以像下面一样使用它。

# js file
const str = 'before';
myCppFunction.doSomething(str);
console.log(str);
// I expect str is now 'changed now!'.

这甚至可能吗?

I want to implement v8 function using c++ via node gyp, which mutates the function parameter.

// c++
using v8::FunctionCallbackInfo;
  using v8::Isolate;
  using v8::Local;
  using v8::Object;
  using v8::Number;
  using v8::String;
  using v8::Value;

  void Method(const FunctionCallbackInfo<Value>&args) {
    Isolate* isolate = args.GetIsolate(); 
    // do something to modify args
    // e.g) args[0] = "changed now!"
  }

so that I can use it like below.

# js file
const str = 'before';
myCppFunction.doSomething(str);
console.log(str);
// I expect str is now 'changed now!'.

Is this even possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

生活了然无味 2025-02-11 02:41:23

(在这里V8开发人员。)定义“可能”。

更明显的答案是“否”。 conder str = ... 之类的变量是对堆上对象的引用(在这种情况下为字符串)。当您调用方法时,此引用的副本将作为参数传递。重新分配什么 arg [0] 点上的点不会影响 str 点,因为它是副本。 方法无法更改 str 点。

哪个使我们转到另一个答案:如果您让 str 继续指向同一字符串,但修改了该字符串的字符? V8不容易让您这样做,因为JavaScript中的字符串被定义为不可变的,但是如果您尽力而为,C ++将使您几乎修改所需的任何内存。但是,这会带来非常奇怪的后果。它将为该程序“打破JavaScript语义”,因为该字符串将在使用的位置更改 。让我将您的示例扩展一点以解释:

const str = 'before';
const backup = str;  // Another reference to the same on-heap object.
myCppFunction.doSomething(str);
console.log(backup);  // What now?

由于JavaScript引擎执行了依赖字符串不可变性的各种内部技巧,因此甚至可以使奇怪的是,例如字符串可以用作其他字符串的一部分(所谓的“ cons”或“ cons”或“ rope”字符串),例如 const rope = str +'一些附加文本'; :如果您覆盖 str 现在的字符,您会在 rope 中看到这一点。 /code>也是 - 但前提
长话短说,虽然从技术上讲这是可能的,但我不建议这样做。 (哦,而且,更改堆上的字符串对象的长度将构成内存损坏并导致崩溃。)

显而易见的选择是使用包装对象,类似于如果您想实现某些东西,则如何执行此操作像这样的JavaScript(或Java或Python等)中这样的类似:

function doSomething(stringWrapper) {
  strWrapper.string = 'changed now';
}

const str = 'before';
const wrapper = {string: str};
doSomething(wrapper);
console.log(wrapper.string);

(V8 developer here.) Define "possible".

The more obvious answer is "no". A variable like constr str = ... is a reference to an object on the heap (this object, in this case, being a string). When you call Method, a copy of this reference is passed along as a parameter. Reassigning what arg[0] points at would not affect what str points at, because it's a copy. There is no way for Method to change what str points at.

Which gets us to the other answer: what if you let str continue to point at the same string, but modified that string's characters? V8 won't easily let you do that, because strings in JavaScript are defined to be immutable, but if you try hard enough, C++ will let you modify almost any memory you want. However, this would have very weird consequences; it would "break JavaScript semantics" for the program, because that string would change everywhere where it's used. Let me expand your example a bit to explain:

const str = 'before';
const backup = str;  // Another reference to the same on-heap object.
myCppFunction.doSomething(str);
console.log(backup);  // What now?

Since JavaScript engines perform various internal tricks that rely on string immutability, this could get even weirder, e.g. strings can be used as part of other strings (so called "cons" or "rope" strings), such as const rope = str + 'some additional text';: if you overwrite str's characters now, you'd see that in rope as well -- but only if you haven't yet performed any operation that caused rope to get "flattened", at which point it's internally turned into full copy of all characters.
Long story short, while this is technically possible, I wouldn't recommend it. (Oh, and also, changing the length of the string object on the heap would constitute memory corruption and result in a crash.)

The obvious alternative is to use a wrapper object, similar to how you would do it if you wanted to implement something like this in pure JavaScript (or Java, or Python, etc):

function doSomething(stringWrapper) {
  strWrapper.string = 'changed now';
}

const str = 'before';
const wrapper = {string: str};
doSomething(wrapper);
console.log(wrapper.string);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文