Problem requiring native c++ addon from electron - node.js

Error when I require a Native Addon C++ from electron that works fin from Node.js
Recently I developed my first native C++ Addon for node that works fine with my node project (node version 10.15.0)
The Addon has been built using XCode, which project has been generating using CMake.
I´m having the following error when I use the same native C++ addon from my Electron app.
dyld: lazy symbol binding failed: Symbol not found: __ZN2v816FunctionTemplate3NewEPNS_7IsolateEPFvRKNS_20FunctionCallbackInfoINS_5ValueEEEENS_5LocalIS4_EENSA_INS_9SignatureEEEiNS_19ConstructorBehaviorENS_14SideEffectTypeE
Referenced from: /Users/vicentvidal/Documents/Desarrollo/DASNet2/dasaudio/build/DASNetAddon.node
Expected in: flat namespace
dyld: Symbol not found: __ZN2v816FunctionTemplate3NewEPNS_7IsolateEPFvRKNS_20FunctionCallbackInfoINS_5ValueEEEENS_5LocalIS4_EENSA_INS_9SignatureEEEiNS_19ConstructorBehaviorENS_14SideEffectTypeE
Referenced from: /Users/vicentvidal/Documents/Desarrollo/DASNet2/dasaudio/build/DASNetAddon.node
Expected in: flat namespace
As I can see the problem appears just when I call from my Electron App
const addon = require('bindings')('DASNetAddon');
which call the following C++ code
static NAN_MODULE_INIT(Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("StreamingWorker").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(2);
SetPrototypeMethod(tpl, "sendToAddon", sendToAddon);
constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
Nan::Set(target, Nan::New("StreamingWorker").ToLocalChecked(),
Nan::GetFunction(tpl).ToLocalChecked());
}
My Electron version is 3.0.10
My Nan version 2.12.1
My bindings version 1.3.1
Does anybody has any suggestion?

I'm not positive that this is the problem but it is possible that, because the function template is missing your C++ class name, the namespace is coming from somewhere else. Here's one of my Nan Init() functions. The line following the // Prepare constructor template qualifies the New argument with a class namespace.
void Metadata::Init(v8::Local<v8::Object> exports) {
Nan::HandleScope scope;
// Prepare constructor template
v8::Local<v8::FunctionTemplate> ctor = Nan::New<v8::FunctionTemplate>(Metadata::New);
constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(2);
ctor->SetClassName(Nan::New("Metadata").ToLocalChecked());
// Prototype
Nan::SetPrototypeMethod(ctor, "copy", Metadata::copy);
Nan::Set(exports, Nan::New("Metadata").ToLocalChecked(), ctor->GetFunction());
}
I haven't tried running/loading in an Electron environment, nor on a Mac, so I can only say this works fine on Linux. But because your error message refers to "FunctionTemplate3New" it's a guess.

Related

Using my native node module with Electron

So i have built a simple node demo module that works fine with node.exe but when i try to require it with atom electron as a module it does not work even though it was linked with the exact same version of node that my version of electron uses and it the same machine type (x86)
I have tried to use the electron source (node.dll.lib) instead but it I get v8 link errors
What is the excepted way to do this?
Severity Code Description Project File Line
Error LNK2019 unresolved external symbol "public: __thiscall v8::HandleScope::HandleScope(class v8::Isolate *)" (??0HandleScope#v8##QAE#PAVIsolate#1##Z) referenced in function "void __cdecl node::NODE_SET_PROTOTYPE_METHOD(class v8::Local,char const ,void (__cdecl)(class v8::FunctionCallbackInfo const &))" (?NODE_SET_PROTOTYPE_METHOD#node##YAXV?$Local#VFunctionTemplate#v8###v8##PBDP6AXABV?$FunctionCallbackInfo#VValue#v8###3##Z#Z) nodeaddon c:\src\justin\nodeaddon\nodeaddon\myobject.obj 1
According to the docs you'd need to rebuild electron with you native module. The easiest way is to use electron-rebuild, which the team provides.
I ended up setting changing my linker and compiler paths to point to the electron as apposed to the node source source and at all works now.

define is not defined, amd-loader vs CommonJs

I am working on first part of this answer
When I compile main.ts to js
require("amd-loader");
import someModule = require('../mymodule')
var someClass = new someModule.MyNamespace.MyClass();
it becomes:
define(["require", "exports", '../mymodule'], function (require, exports, someModule) {
require("amd-loader");
var someClass = new someModule.MyNamespace.MyClass();
});
then it gives me define is not defined error
When I modify it as below, error goes away.
require("amd-loader");
define(["require", "exports", '../mymodule'], function (require, exports, someModule) {
var someClass = new someModule.MyNamespace.MyClass();
});
Then I get Cannot read property 'MyClass' of undefined error
How can I get fix these error and get it work as expected as mentioned in that Q&A?
My environment is Visual Studio 2015 and I compile with AMD options as module system(obviously I tried each options). I am doing angular protractor e2e tests
As said by basarat at this answer, CommonJS should be used in this case.
In Visual Studio 2015 version 14.0.23.107.0, it seems TypeScript Module System options does not work, and it compiles always with whatever any one selected
So following this post CommonJS can be selected.
And voila it compile in with CommonJS and works as expected

VS2013 VC++ libcurl LNK2028 LNK2019 linking errors

I'm trying to get Libcurl working in my VC++ project on VS2013 Community. I've been toiling with this for many hours, and I've tried essentially everything on Stack and Google about it, to no avail.
My most recent attempt was sparked by this answer, that mentions libcurl as a Nuget package. This is good, because it comes with all of the .lib files required. I have however run into the same problem as this fellow, in that I'm getting a linker error.
I'm importing the following libraries as 'Additional Dependencies' in the Project Configuration settings under Linker -> Input:
libcurl.lib;libeay32.lib;ssleay32.lib;Ws2_32.lib;libssh2.lib;zlib.lib;wldap32.lib;
Obviously, each one of these .lib files is in a different directory inside the nuget package folder inside the project folder, so under Linker -> General my 'Additional Library Directories' is set to:
"PATHTOPROJECT\packages\curl.7.30.0.2\build\native\lib\v110\x64\Release\static";
"PATHTOPROJECT\packages\zlib.1.2.8.1\build\native\lib\v110\Win32\Release\static\cdecl";
"PATHTOPROJECT\packages\openssl.1.0.1.21\build\native\lib\v110\x64\Release\static\cdecl";
"PATHTOPROJECT\packages\libssh2.1.4.3.1\build\native\lib\v110\x64\Release\static\cdecl";
I am trying to use static libraries, because I don't want to drag .dll's with my project executable if I can avoid it. It's also worth noting that my most recent attempt at using libcurl also includes SSL and whatnot, but I don't actually need those extras. Really, I just need a static libcurl library, but I can't find or compile one it seems.
In my code, I'm also using this include: #include "curl/curl.h"
I've also added the Additional Include directory correctly under 'Additional Include Directories' under C/C++ -> General:
PROJECTPATH\packages\curl.7.30.0.2\build\native\include
Now, this all compiles fine as long as I don't try and use curl in the project code.
So, the errors when I do try and use curl in the code:
CURL *curl;
curl = curl_easy_init();
That piece of code generates these errors:
1>Main.obj : error LNK2028: unresolved token (0A000453) "extern "C" void * __cdecl curl_easy_init(void)" (?curl_easy_init##$$J0YAPAXXZ) referenced in function "private: class System::String ^ __clrcall Project::Main::CurlRequest(class System::String ^,class System::String ^,class System::String ^,class System::String ^)" (?CurlRequest#Main#Project##$$FA$AAMP$AAVString#System##P$AAV34#000#Z)
1>Main.obj : error LNK2019: unresolved external symbol "extern "C" void * __cdecl curl_easy_init(void)" (?curl_easy_init##$$J0YAPAXXZ) referenced in function "private: class System::String ^ __clrcall Project::Main::CurlRequest(class System::String ^,class System::String ^,class System::String ^,class System::String ^)" (?CurlRequest#Main#Project##$$FA$AAMP$AAVString#System##P$AAV34#000#Z)
There is of course more to my curl using code, but that bare minimum shows the basics of the linking error. What can I do to fix this? As I mentioned before I've tried a whole range of solutions, some of which I'll list below:
Many answers to the questions regarding problems using libcurl in VS projects mention downloading libcurl from http://curl.haxx.se/latest.cgi?curl=win32-devel-msvc, but that link doesn't work as of now, so I can't use it.
More answers say to just compile libcurl from source. The source comes with .vcproj files, none of which compile for me without hundreds of errors, so that's out.
Solved.
This Github project is a .bat file that downloads the libcurl source, compiles it, and makes the libraries (both static and dynamic). Importing the static library created by this (libcurl_a.lib) and using it in my project along with the include directory has worked.
I'll leave this question with an unaccepted answer in case someone can provide other helpful steps that would have fixed the problem I had in using the nuget package installation.
Finally.

Haxe: How to use a .NET C++/CLI dll in haxe code?

I've been trying to use Haxe to generate C# code that calls methods from a dll written in C++/CLR. This dll is called "AudioClientSDK.dll"
Here is an example of the Haxe code I'm trying:
package hello;
class HelloWorld {
static public function main():Void {
var s = untyped __cs__("AudioClientCLR.AudioClientAPI.release()");
}
}
As you can see I'm using "Haxe magic" syntax (I previously tried Haxe extern classes that resulted pretty much in the same problems) to directly call the release method within the AudioClientSDK.dll. The method signature inside the dll is:
public : void AudioClientCLR::AudioClientAPI::release()
However, when I try to compile this code, Haxe throws this error:
haxe -cp src -cs out/CS -main hello.HelloWorld
haxelib run hxcs hxcs_build.txt --haxe-version 3103
c:\git\HelloHaxe\src\hello\HelloWorld.hx(6,16): error CS0103: The name
'AudioClientCLR' does not exist in the current context
Compilation error
Native compilation failed
Error: Build failed
If I try to pass the AudioClientSDK.dll reference as -net-lib or -net-std I get these errors:
haxe -cp src -cs out/CS -net-lib lib/CPP/x86/AudioClientSDK.dll -main hello.HelloWorld
File "ilMetaReader.ml", line 281, characters 36-42: Assertion failed
error 0x2
haxe -cp src -cs out/CS -net-std lib/CPP/x86/AudioClientSDK.dll -main hello.HelloWorld
Error: No .NET std lib directory with the pattern 'net-20' was found in the -net-std search path. Try updating the hxcs lib to the latest version, or specifying another -net-std path.
Do any of you know how to correctly use the dll?
Thanks in advance.
P.S. These are some properties of the AudioClientSDK.dll:
Targeted framework: .NETFramework,Version=v4.0
Platform: Win32
Platform Toolset: VisualStudio 2010 (v100)
Use of MFC: Use MFC in a Shared DLL
Common Language Runtime: Common Language Runtime Support (/clr)
Also, please note that this dll can be used without problems from C# in Visual Studio.
This seems like a bug. Please report it ASAP to the haxe issue list, with a downloadable link to the offending dll, and it might get included inyo the 3.2 final release

Node.js module - adding link dependency

I'm working on a Node.js wrapper module for a colleagues C library. The library is created in Shared Object (.so) form for dynamic linking.
My CPP module file begins with
#include "path/to/lib/source/lib.h"
and is built with the following wscript
def set_options(ctx):
ctx.tool_options('compiler_cxx')
def configure(ctx):
ctx.check_tool('compiler_cxx')
ctx.check_tool('node_addon')
ctx.env.append_value('LINKFLAGS', ['-l:lib.so', '-L/path/to/lib.so/'])
def build(ctx):
t = ctx.new_task_gen('cxx', 'shlib', 'node_addon')
t.source = ['module.cpp']
t.target = 'module'
When I then proceed to call into my module, which in turns call the library, i get the following error:
node: symbol lookup error: <path/to/module.node>:
undefined symbol: <name of library call>
I tried dumping the dependencies of the module with 'ldd module.node' and I got a little suspicious as it doesn't mention my .so file.
Any help is much appreciated!
Do you know if the dynamic linker can find your library? Try adding the library path to your LD_LIBRARY_PATH. You can run this in the shell before you invoke Node with your test script:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/lib.so/
node test-script.js
(On a Mac, that would be DYLD_LIBRARY_PATH.)

Resources