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 (i.e. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With