Reputation: 301
I have a NodeJS app that makes some calls to a native addon that implements some OpenCV calls. The node-gyp build
command succeeds, but everytime I try to run the server with node app
I get:
Error: /home/cmaccess/SfMLocalization/VisionLocalizeServer/build/Release/localizeImage.node: undefined symbol: _ZNK2cv9Feature2D5emptyEv
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at bindings (/home/cmaccess/SfMLocalization/VisionLocalizeServer/node_modules/bindings/bindings.js:76:44)
at Object.<anonymous> (/home/cmaccess/SfMLocalization/VisionLocalizeServer/routes/localize.js:28:37)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
I cannot, for the life of me, figure out why this is happening. I checked out a known good revision and reinstalled OpenCV. I'm not even using cv::Feature2D
explicitly in any code! Does anyone have a suggestion as to what might be causing this undefined symbol error?
Upvotes: 3
Views: 5310
Reputation: 1295
Found that if something included by "#include something.h" then the compile will be OK but the "undefined symbols" will be displayed if I use (in my case) some new instance like "new Something()". So I should include the "something.cpp" in the binding.gyp in the sources part:
"sources": [ "something.cpp" ]
Upvotes: 0
Reputation: 63
I had a problem similar to this one, and my opencv was badly installed (?). Reinstalling it solved the problem.
Upvotes: 1
Reputation: 691
There are a few things to check when linking a library and and then subsequently trying to load it. In Linux for example, all the symbols only need to be available at the final load stage (loading the executable), with node this will be when you run node and load the native addon. To force the node addon build to fail if there are missing symbols you must pass -z defs
as a linker option in node-gyp. So you would add the following in your binding.gyp to the "link_settings" element or where appropriate:
"ldflags": [
"-Wl,-z,defs"
]
Please look at a node-gyp tutorial (something like this) if you don't know how to edit building and linking.
Note: It appears that node defers symbol loading of a lot of its internals as well, so unfortunately you are going to get a whole lot of undefined symbols for v8 stuff as well. This is probably unavoidable as node loads these symbols dynamically. You will have to inspect the output and pipe it to a pager or grep to find opencv missing symbols. The names will not be mangled at this stage. When you are done remove those flags.
If you get opencv undefined errors here it means you are linking the library incorrectly or not at all. Some things to look out for are:
-z defs
;You can use nm to look what symbols are defined in your final node addon... anything with a "U" (undefined) is expected to be made available at the final load stage. You should still see the opencv symbols as undefined unless you statically linked opencv. So call:
$ nm -C myaddon.node
The -C will demangle the names, you should see cv::Feature2D as undefined if you linked the shared library. The final step is to check what libraries will be loaded when your library is loaded. Use ldd to do this.
$ ldd myaddon.node
This will show you any libraries that could not be found. If the opencv libraries are not found here you have not linked the shared library. It will also show you where it finds the libraries if it does find them (you can use these paths to make sure you are using your checked out libraries).
Just a final nuclear option, opencv has quite a few libraries it seems, your best best is to link all of them to resolve missing symbols. Get all those libs with pkgconfig:
$ pkg-config --libs opencv
You can get the include flags with
$ pkg-config --cflags opencv
Put that stuff in the appropriate places in your binding.gyp.
Upvotes: 12