node.js c ++将多个cc文件扩展到一个模块中

时间:2014-04-03 09:39:47

标签: javascript c++ node.js

我正在使用node.js来评估基于complexe c的库如何与node.js连接。此lib对数据库执行多个操作,nodejs应调用此函数并通过rest api返回结果。

在使用node.js方面的示例时,我遇到了一个问题:

我正在尝试根据两个cc文件构建一个插件:

addon1.c:

#define BUILDING_NODE_EXTENSION
#include <node.h>

using namespace v8;

Handle<Value> Add(const Arguments& args) {
  HandleScope scope;

  if (args.Length() < 2) {
    ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
    return scope.Close(Undefined());
  }

  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
    ThrowException(Exception::TypeError(String::New("Wrong arguments")));
    return scope.Close(Undefined());
  }

  Local<Number> num = Number::New(args[0]->NumberValue() +
      args[1]->NumberValue());
  return scope.Close(num);
}

void Init(Handle<Object> exports) {
  exports->Set(String::NewSymbol("add"),
      FunctionTemplate::New(Add)->GetFunction());
}

NODE_MODULE(addon, Init)

addon2.c:

#define BUILDING_NODE_EXTENSION
#include <node.h>

using namespace v8;

Handle<Value> Del(const Arguments& args) {
  HandleScope scope2;

  if (args.Length() < 2) {
    ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
    return scope2.Close(Undefined());
  }

  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
    ThrowException(Exception::TypeError(String::New("Wrong arguments")));
    return scope2.Close(Undefined());
  }    

  Local<Number> num = Number::New(args[0]->NumberValue() -
      args[1]->NumberValue());
  return scope2.Close(num);
}

void Init(Handle<Object> exports) {
  exports->Set(String::NewSymbol("del"),
      FunctionTemplate::New(Del)->GetFunction());
}

NODE_MODULE(addon, Init)

我的binding.gyp:

{
  "targets": [
    {
      "target_name": "addon",
      "sources": ["addon1.cc", "addon2.cc"]
    }
  ]
}

调用node.gyp configure build以及以下错误消息结束:

  CXX(target) Release/obj.target/addon/addon2.o
  SOLINK_MODULE(target) Release/addon.node
duplicate symbol __Z4InitN2v86HandleINS_6ObjectEEE in:
    Release/obj.target/addon/addon1.o
    Release/obj.target/addon/addon2.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Release/addon.node] Error 1
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/opt/local/lib/node_modules/node-gyp/lib/build.js:267:23)
gyp ERR! stack     at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (child_process.js:797:12)
gyp ERR! System Darwin 13.1.0
gyp ERR! command "node" "/opt/local/bin/node-gyp" "configure" "build"
gyp ERR! cwd /Applications/MAMP/htdocs/nodejs/test2
gyp ERR! node -v v0.10.26
gyp ERR! node-gyp -v v0.13.0
gyp ERR! not ok 

我希望你们中的任何人都有提示如何解决这个问题。

提前致谢。

2 个答案:

答案 0 :(得分:1)

问题非常明确:在两个翻译单元(源文件)中都有一个名为Init的函数。在构建单个模块时,您应该只有一个Init函数。

解决此问题的简单方法是删除一个Init函数,并在剩余的add函数中“注册”delInit个名称。


解决方案:在 一个 源文件中,您只有 Init功能,并且< em>声明缺少的AddDel函数(即你创建函数原型):

// Declare function prototypes
Handle<Value> Add(const Arguments& args);
Handle<Value> Del(const Arguments& args);

// The one and only initialization function
void Init(Handle<Object> exports) {
  exports->Set(String::NewSymbol("add"),
      FunctionTemplate::New(Add)->GetFunction());
  exports->Set(String::NewSymbol("del"),
      FunctionTemplate::New(Del)->GetFunction());
}

NODE_MODULE(addon, Init)

实际上,您现在可以将其作为单独的源文件。

答案 1 :(得分:0)

从您的实施中我可以看到您正在尝试实施两个不同的模块add和del

node.js提供了http://nodejs.org/api/addons.html

建议的不同类型的插件模式

在我看来,您尝试实施的内容可以通过Wrapping C++ objects

获得