I'm trying to create own c++ addon to node from code that was written by my collegue.
It compiles to file.node and then it crashes when I try to use it in node.
I have tried to prebuild library, then use library.dylib and also to build it together by node-gyp.
Both of these approaches compile and throw an error on runtime.
What else can I do?
I'm working on OSX Mojave.
I've checked:
How to include c++ libraries so that node-gyp can link?
dyld: lazy symbol binding failed
Whole error:
dyld: lazy symbol binding failed: Symbol not found:
__ZN3mds7computeERNSt3__16vectorINS1_IdNS0_9allocatorIdEEEENS2_IS4_EEEE
Referenced from: /.../node_folder/build/release/file.node
Expected in: flat namespace
My gyp file:
{
"targets": [
{
"target_name": "name",
"sources": ["file.cc"],
"include_dirs": [
"<!(node -e \"require('nan')\")",
"/path/to/cpp/src/"
],
"link_settings": {
"libraries": ["-L/path/to/dylib/directory"]
},
"libraries": ["-L/path/to/dylib/directory"]
}
]
}
My package.json
{
...
"dependencies": {
"nan": "^2.12.1",
"node-gyp": "^3.8.0"
},
"scripts": {
"compile": "node-gyp rebuild",
"start": "node index.js"
},
"gypfile": true
}
My binding file:
#include <nan.h>
#include <iostream>
#include <my_header_file.h>
using namespace v8;
NAN_METHOD(compute)
{
if (!info[0]->IsArray())
{
Nan::ThrowTypeError("Argument myst be an array");
return;
}
...
std::vector<std::vector<double>> vector;
... (filling the vector with data)
//static std::vector<std::vector<double>> compute(std::vector<std::vector<double>> & distances_matrix);
mds::compute(vector);
}
NAN_MODULE_INIT(Initialize)
{
NAN_EXPORT(target, compute);
}
NODE_MODULE(addon, Initialize);
I see you are importing your header at #include <my_header_file.h>.
If you are calling a method from your custom class for your NAN_METHOD you need to call it inline or else the compiler will not know where to look.
Run "c++filt (missing symbol)" to demangle and see where you need to call it
Example
Instead of method()
Use Class::method()
Your missing symbol demangled is mds::compute(std::__1::vector<std::__1::vector<double, std::__1::allocator<double> >, std::__1::allocator<std::__1::vector<double, std::__1::allocator<double> > > >&)
I have solved from https://github.com/nodejs/node-gyp/issues/1380,
The missing symbol's name indicates it's not using C linkage.
I just add extern "C" in the header file
extern "C" double add(double a ,double b);
Related
This question already has answers here:
Why is "using namespace std;" considered bad practice?
(41 answers)
Closed 9 months ago.
I am very new to coding in C++ and have little to no experience at all. My problem is: I wanted to use strings so i added #include to the includes in my code but VSCode tells me identifier "string" is undefinedC/C++(20). What I have done is added and modified a c_cpp_properties.json file vor VSCode:
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
But that didn't solve the problem. Also, I have made sure that C++ is installed, including the g++ compiler. In VSCode I am using following C++ plugins / addons: C/C++ and C/C++ Project Generator (which I don't really use).
This is the relevant part of my code:
#include <iostream>
#include <string>
int main(int argc, char *argv[])
{
string s;
return 0;
}
And this is the error log / debug message:
g++ -std=c++17 -Wall -Wextra -g -Iinc -c src/main.cpp -o src/main.o
src/main.cpp: In function ‘int main(int, char**)’:
src/main.cpp:30:2: error: ‘string’ was not declared in this scope
30 | string s;
| ^~~~~~
src/main.cpp:30:2: note: suggested alternatives:
In file included from /usr/include/c++/9/iosfwd:39,
from /usr/include/c++/9/ios:38,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from src/main.cpp:1:
/usr/include/c++/9/bits/stringfwd.h:79:33: note: ‘std::string’
79 | typedef basic_string<char> string;
| ^~~~~~
In file included from /usr/include/c++/9/bits/locale_classes.h:40,
from /usr/include/c++/9/bits/ios_base.h:41,
from /usr/include/c++/9/ios:42,
from /usr/include/c++/9/ostream:38,
from /usr/include/c++/9/iostream:39,
from src/main.cpp:1:
/usr/include/c++/9/string:67:11: note: ‘std::pmr::string’
67 | using string = basic_string<char>;
| ^~~~~~
Solution: Replace string s; with std::string s;.
C++ strings are "hidden" inside the std namespace. The compiler doesn't recognize string because of that.
You could either include the entire std namespace:
using namespace std;
Do this for specifically strings and nothing else:
using std::string;
or type std::string instead of string when initializing strings. The C++ Standard Library is in the compiler's include path by default, you don't need to do anything extra to be able to use its headers.
I am trying to compile the below program. However it's giving me the error: unknown type name 'constexpr' error. What should I do?
Code:
//this is model.cpp. battery.cpp and load.cpp are two secondary files
#include "load.h"
#include "battery.h"
//compile time constants - Settings
constexpr int intervals = 96;
constexpr float e_min = 0.001;
constexpr int max_iters = 100;
constexpr int nloads = 10;
constexpr int nbat = 10;
struct devices
{
load loadDevices[nloads];
battery batteryDevices[nbat];
};
int main()
{
//Initialization of the model
devices devices1;
return 0;
}
I get the same error on each line where constexpr is used.
error: unknown type name 'constexpr'
constexpr int intervals = 96;
My C/C++ configurations .json file is as follows:
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"macFrameworkPath": [],
"compilerPath": "/usr/local/bin/gcc-11",
"cStandard": "gnu17",
"cppStandard": "gnu++17",
"intelliSenseMode": "macos-gcc-x64"
}
],
"version": 4
}
System: MACOSX
IDE: VSCode
Compiling on Mac's Terminal using g++
compilation command: g++ model.cpp battery.cpp load.cpp
That json config is not used if you are calling the compiler directly from the command line. In that case you have to specify every option yourself:
g++ -std=gnu++17 -Wall -Werror model.cpp battery.cpp load.cpp
I just added -Wall -Werror for good measure, you should never compile your code without them.
Without the -std option the compiler uses an older version of the C++ standard that does not have constexpr.
What I am trying to do is very simple, I need to create a vector that can hold different types of data. So I read about std::variant and am trying to use it, however, when declaring my "std::vector< std::variant< typenames > >", the compiler complains about not finding the declaration for variant<> even though I included the variant library.
(errors are "use of undeclared identifier variant" with implicit namespace, and "no member named 'variant' in namespace 'std'" with explicit namespace). My Clang version is 11, and I am using c++17, so I don't know what I could be missing here. For what it's worth, I am currently using VScode 1.53. This is my c_cpp_properties.json :
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include/"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "linux-clang-x64"
}
],
"version": 4
}
I have tried also changing the cpp version in the default GUI provided by vscode to manage the cpp compiler, that made no difference.
What I am doing is something similar to this:
#include <vector>
#include <variant>
struct c {
std::vector< std::variant<glm::vec2, glm::vec3, glm::vec4>> v;
};
Does anyone have any idea why this is happening, or had this problem before and knows a solution?
Solution:
Turns out specifying the cpp standard on the file c_cpp_properties.json is not enough. You have to add "-std=c++17" to tasks.json as well, after "-g", like this:
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: clang++ build active file",
"command": "/usr/bin/clang++",
"args": [
"-g",
"-std=c++17",
...
I am not a Clang expert, but try using the option -std=c++17.
According to this the default seems to be C++98.
This appears to work fine in MSVC:
#include <variant>
struct c {
std::vector< std::variant<int, float>> v;
}
It seems like the compiler might be throwing a fit about the template type nesting(wild guess here). Maybe try the following as a workaround:
#include <variant>
struct c {
typedef std::variant< int, float> TwoPartVariant;
std::vector< TwoPartVariant> v;
};
I'm going crazy for this problem. I downloaded the source code and pre-compiled files of sqlite3 according to the tutorial, and used vs to compile, got the sqlite3.lib and sqlite3.exp files, and put it in the C: \ sql folder. Then I created the project in vscode, and put sqlite3.h in the root directory of the project, and created the following test code.
#include "sqlite3.h"
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable : 4996)
#pragma comment(lib, "c:\\sql\\sqlite3.lib")
int main() {
sqlite3 *db = NULL;
char *zErrMsg = 0;
int rc;
rc = sqlite3_open("Student.db", &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
} else
printf("open mydata successfully!\n");
sqlite3_close(db);
system("pause");
return 0;
}
My tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "gdb",
"type": "shell",
"command": "g++",
"args": [
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"-LC:\\sql",
// "${fileDirname}\\src\\Account.cpp",
// "${fileDirname}\\src\\Person.cpp",
// "${fileDirname}\\src\\Date.cpp",
// "${fileDirname}\\src\\System.cpp",
// "${fileDirname}\\src\\Administrator.cpp",
"-lsqlite3",
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
But no matter how I modify the tasks.json file, I still get the following result. I am really too lost. Can anyone help me how to solve this problem?
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Drew\AppData\Local\Temp\ccUXavQh.o:test.cpp:(.text+0x2e): undefined reference to `sqlite3_open'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Drew\AppData\Local\Temp\ccUXavQh.o:test.cpp:(.text+0x45): undefined reference to `sqlite3_errmsg'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Drew\AppData\Local\Temp\ccUXavQh.o:test.cpp:(.text+0x6d): undefined reference to `sqlite3_close'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Drew\AppData\Local\Temp\ccUXavQh.o:test.cpp:(.text+0x91): undefined reference to `sqlite3_close'
collect2.exe: error: ld returned 1 exit status
I personally download the sqlite-amalgamation source and compile it as a regular source file. SQLite made it very easy and you should have no problem https://www.sqlite.org/download.html
I don't mess with static/dynamic libs when I don't need to. The problem may occur because of which compiler compiled the library (ie ms compiler, mingw, clang, etc). There's a chance you may be mixing them causing the error. I suspect the precompile one is using ms compiler. From memory clang works with libs compiled with ms compiler (clang depends on it). mingw doesn't depend on it and won't use ms compiled libs
Normally I use VS19 for C++ programming, but I wanted to try if it works on VSCode on my Macbook, so I wrote a real simple program:
main
#include <iostream>
#include "test.hpp"
using namespace std;
int main()
{
testfile obj(5);
cout << "main.cpp" << endl;
obj.output();
return 0;
}
class header (.hpp)
#pragma once
using namespace std;
class testfile
{
private:
int i;
public:
testfile(int in) : i(in) {}
void output();
};
class file (.cpp)
#include "test.hpp"
#include <iostream>
using namespace std;
void testfile::output()
{
cout << i << endl;
}
I know I could write the little output in the header, but I want to try if it works if the code is split up into many different files. I get the following error:
(PATH)..\Temp\ccITg6NM.o:main.cpp:(.text+0x48): undefined reference to
`testfile::output()' collect2.exe: error: ld returned 1 exit status
The same goes for my windows laptop. I ran the exact same code on Visual Studio and it worked perfectly fine. I tried googling the error but tbh, I didn't got anything out of it...
I run VSCode with C/C++ intellisense and the compile & run plugin.
It's pretty tricky... I'm not sure but the linker maybe ignore the implementation of testfile::output() in test.cpp because the header test.hpp include implementation of constructor testfile::testfile(int in).
I actually cannot reproduce the problem, try this :
test.hpp
#pragma once
using namespace std;
class testfile
{
private:
int i;
public:
testfile(int in);
void output();
};
test.cpp
#include "test.hpp"
#include <iostream>
using namespace std;
testfile::testfile(int in) : i(in) {}
void testfile::output()
{
cout << i << endl;
}
I think it is better that all implementation are in *.cpp file like above.
EDIT :
I use g++ for compiling those files(I'm sorry I don't have VScode environment).
command line(correct) :
g++ main.cpp test.cpp -o out
output :
D:\workspace\test2\test2>out
main.cpp
5
command line(incorrect, test.cpp is missing) :
g++ main.cpp -o out
output :
${User}\AppData\Local\Temp\ccYKJ92L.o:main.cpp:(.text+0x1a): undefined reference to `testfile::testfile(int)'
${User}\AppData\Local\Temp\ccYKJ92L.o:main.cpp:(.text+0x48): undefined reference to `testfile::output()'
collect2.exe: error: ld returned 1 exit status
command line(incorrect, main.cpp is missing) :
g++ test.cpp -o out
output :
C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x2e): undefined reference to `WinMain'
collect2.exe: error: ld returned 1 exit status
EDIT2 :
I installed VSCode although I use windows, I think I figured out why these type of error occur.
You might use F6 command for build the sources w/ C/C++ Compile Run, but the F6 command is applied only for a file which is currently selected and showed on editor. You select main.cpp then linker cannot find method of class testfile, otherwise select test.cpp then linker cannot find entry point(main) of project.
So if you want to build correctly, you must make kind of build script(makefile, json, something).
If you type Ctrl+Shift+P, you can fild Tasks: Configure task tab. Click them and configure your setting(host OS, compiler, ...) It would gives you default tasks.json file with minimal form.
I use this json file(Windows, mingw(gcc for windows))
tasks.json
{
"version": "2.0.0",
"command": "g++",
// compiles and links with debugger information
"args": ["-g", "-o", "out.exe", "main.cpp", "test.cpp"],
}
Ctrl+Shift+B (build using above json), then its output:
running command> g++ -g -o out.exe main.cpp test.cpp
It builds out.exe file successfully.
If you want to debug or run, use F5 or Ctrl+F5 or Debug tab on the top menu bar, then its output on debug console:
main.cpp
5
Debug or run step refers to launch.json file like build step refers to tasks.json file.
for reference, launch.json :
{
"version": "0.2.0",
"configurations": [
{
"name": "(Windows)build test",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/out.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false
}
]
}
Concolusionally it's not problem of source.
For further infomation refer to this post :
How do I set up Visual Studio Code to compile C++ code?