electron: [Bug]: Link error for native c++ modules
Preflight Checklist
- I have read the Contributing Guidelines for this project.
- I agree to follow the Code of Conduct that this project adheres to.
- I have searched the issue tracker for a feature request that matches the one I want to file, without success.
Electron Version
13.1.4
What operating system are you using?
Windows
Operating System Version
Windows 10 Home (19042)
What arch are you using?
x64
Last Known Working Electron version
No response
Expected Behavior
The native module in the testcase gist should be able to link. The problematic part is the function v8::ArrayBuffer::GetBackingStore()
Actual Behavior
Linking fails with the error
error LNK2019: unresolved external symbol "__declspec(dllimport) public: class std::shared_ptr<class v8::BackingStore> __cd ecl v8::ArrayBuffer::GetBackingStore(void)" (__imp_?GetBackingStore@ArrayBuffer@v8@@QEAA?AV?$shared_ptr@VBackingStore@v8@@@std@@XZ) re ferenced in function "void __cdecl foobar(class v8::FunctionCallbackInfo<class v8::Value> const &)" (?foobar@@YAXAEBV?$FunctionCallbac kInfo@VValue@v8@@@v8@@@Z) [c:\Work\repro_bug_arraybuffer\build\foobar.vcxproj]
Testcase Gist URL
https://gist.github.com/TanninOne/d321ab1676798647cf672f08e78b88d8
Additional Information
Building the same module for node 14.17.1 works fine.
The error message, although cryptic, is correct: the header and link library shipped do not seem to match. the header declares GetBackingStore like this:
std::shared_ptr<BackingStore> GetBackingStore();
but the library exports this:
?GetBackingStore@ArrayBuffer@v8@@QEAA?AV?$shared_ptr@VBackingStore@v8@@@__1@std@@XZ
which demangles to
public: class std::__1::shared_ptr<class v8::BackingStore> __cdecl v8::ArrayBuffer::GetBackingStore(void) __ptr64
so as far as I understand it the namespace is different and thus the linker doesn’t find the function.
node.exe version 14.17.1 otoh exports
?GetBackingStore@ArrayBuffer@v8@@QEAA?AV?$shared_ptr@VBackingStore@v8@@@std@@XZ
aka
public: class std::shared_ptr<class v8::BackingStore> __cdecl v8::ArrayBuffer::GetBackingStore(void) __ptr64
which matches the declaration in v8.h exactly.
With prior versions of electron (up to 12 I think) we could use the deprecated function GetContent to get at the content of an ArrayBuffer but that function has been removed so until this is fixed, if I’m not completely mistaken, any native module that requires access to the content of an ArrayBuffer, including helper libraries like nan or nbind and all modules that depend on those will be broken.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 3
- Comments: 21 (10 by maintainers)
@VerteDinde, I find the decision to build Electron on Windows using a C++ runtime that it just out of beta instead of the MS C++ runtime highly unusual - but there is probably a good reason for it. But in this case, I suggest that you also include this runtime along the
node.lib
DLL import library so that native modules can link with it. Currently, if I want to port my native Node.js addon to Electron I have only two choices and both are horrible:std::shared_ptr
as some people in this thread didlibc++
for WindowsAll of this renders the port of a native Node.js addon to Electron a huge undertaking and completely destroys the dream of simply launching
electron-rebuild
and going for a cup of coffee.I ended up adding the following to my
node-gyp
config:And using the follow
#if
Not the most elegant or low cost solution, but hopefully that works as a stop gap while my users migrate to Node-API.
Is there a
#def
that can be used to tell if the module is being built for electron? My solution was a bit convoluted.Just a note: I’d recommend that all native modules use N-API and avoid nan, for this kind of reason. C++ ABIs are very difficult to stabilize. N-API is explicitly designed as a stable ABI target. https://nodejs.org/api/n-api.html
@somanuell That’s a sample of the neon project source.
Neon_Buffer_Data
is a very small helper that gets the contents of the buffer:The result of
node::Buffer::New
goes intolocal
and thennode::Buffer::Data
can be used to get the buffer data out.Yep, using the same clang + std library that Electron uses to build is the safest way to build native modules that interact with the std library.