简体   繁体   中英

node.js c++ extension multiple cc files into one module

i´m playing a little bit with node.js to evaluate how a complexe c based library could be connected with node.js. This lib perform several actions with a database and nodejs shall call this functions and return the results via rest api.

While playing aroung with the examples from the node.js side, i faced a problem:

I´m trying to build one addon based on two cc files:

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)

And my binding.gyp:

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

calling node.gyp configure build ends with following error messages:

  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 

I hope anyone of you have a hint how to solve this issue.

Thanks in advance.

The problem is pretty clear: You have a function named Init in both translation units (source files). As you are building a single module, you should have only one Init function.

The simple way to solve this is to remove one Init function, and "register" both add and del names in the remaining Init function.


Solution: In one source file you have the only Init function, and declare the missing Add or Del function (ie you make function prototypes):

// 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)

Actually, you can now have this as a separate source file.

From your implementation I can see you are trying to implement TWO DIFFERENT MODULES add and del .

node.js provides different types of Addon Patterns as suggested by http://nodejs.org/api/addons.html

In my opinion, what you are trying to implement can be obtained by Wrapping C++ objects

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM