简体   繁体   中英

Node app with C++ addon complains about undefined symbol at runtime

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?

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:

  • if you have all the -lopencv_* library link flags in a "libraries" element somewhere, if you don't you are not actually linking opencv but it would not normally complain without -z defs ;
  • if it is linking the library which corresponds to the headers you are using (the easiest way to avoid these kind of problems is just to use your distribution's opencv). You can be explicit about these things, if you need to use a checked out version of opencv, in your binding.gyp, by setting build flags for include and library search paths.

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.

I had a problem similar to this one, and my opencv was badly installed (?). Reinstalling it solved the problem.

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" ]

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