javascript equivalent for python ctypes with node-gyp - node.js

I want to transform a python script into a javascript script. My python script loads a dll and use its API.
processings2D = ctypes.CDLL('processings2D.dll')
print(processings2D.ImageProcessor2DCreate())
I try do to the same with node-gyp but my script doesn't find the dll.
console.log(processings2D.ImageProcessor2DCreate());
^
TypeError: Cannot load processings2D.dll library
test.js
var processings2D = require('./build/Release/processings2D.node');
console.log(processings2D.ImageProcessor2DCreate());
addon.cc
#include <nan.h>
#include "processings2D/processings2D.h"
HINSTANCE hDLL = NULL;
typedef int(*Fn)();
void ImageProcessor2DCreate(const Nan::FunctionCallbackInfo<v8::Value>& info) {
hDLL = LoadLibrary("processings2D.dll");
if(!hDLL)
{
Nan::ThrowTypeError("Cannot load processings2D.dll library");
return;
}
Fn fn = (Fn)GetProcAddress(hDLL, "ImageProcessor2DCreate");
if (!fn) {
Nan::ThrowTypeError("Could not load ImageProcessor2DCreate function");
FreeLibrary(hDLL);
return;
}
info.GetReturnValue().Set(Nan::New(fn()));
}
void Init(v8::Local<v8::Object> exports) {
exports->Set(Nan::New("ImageProcessor2DCreate").ToLocalChecked(), Nan::New<v8::FunctionTemplate>(ImageProcessor2DCreate)->GetFunction());
}
NODE_MODULE(twoD, Init)
binding.gyp
{
"targets": [
{
"target_name": "processings2D",
"sources": [
"addon.cc"
],
"include_dirs": [
"<!(node -e \"require('nan')\")"
]
}
]
}
dll is in the Release folder /build/Release/processings2D.dll
Am I in the right direction ?

The solution was really simple :
My dll was a 32 bit version, so I should build my module with the 32 bit arch flag and execute my test with the 32 bit version of node.
node-gyp clean configure --arch=ia32 build
"C:\Program Files (x86)\nodejs\node.exe" test.js

Related

Need to create node native module using an electron app

I am creating a simple electron app with native modules included. I have included some static libraries sourced from c++ application. Here is my binding.gyp file and the hello.cc file created as mentioned in the https://nodejs.org/dist/latest/docs/api/addons.html
Here is my binding.gyp file
binding.gyp:
"targets": [
{
"target_name": "myext",
"libraries": [
"/Users/rsivaram/logitech/obs-studio/deps/w32-pthreads/libpthreadGC2.a",
"/Users/rsivaram/logitech/obs-studio/build/plugins/obs-x264/libobs-x264-util.a",
"/Users/rsivaram/logitech/obs-studio/build/plugins/mac-syphon/libsyphon-framework.a",
"/Users/rsivaram/logitech/obs-studio/build/deps/file-updater/libfile-updater.a",
"/Users/rsivaram/logitech/obs-studio/build/deps/libcaption/libcaption.a",
"/Users/rsivaram/logitech/obs-studio/build/deps/media-playback/libmedia-playback.a",
],
"cflags!": [ "-fno-exceptions" ],
"cflags": [ "-std=c++11" ],
"cflags_cc!": [ "-fno-exceptions" ]
}
]
}
Here is my hello.cc file
hello.cc:
#include <node.h>
namespace demo {
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(String::NewFromUtf8(
isolate, "world").ToLocalChecked());
}
void Initialize(Local<Object> exports) {
NODE_SET_METHOD(exports, "hello", Method);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
} // namespace demo
"npm install" works fine, however I m not able to run the application using "npm start".
Errors I m getting
1."identifier "v8" is undefined" in the hello.cc file.
2. "Module did not self-register <abs path of the app>/electron-quick-start/build/Release/myext.node "
How do I create the hello.cc file. Please let me know. Thanks

ubuntu18.04 vscode kernel module program ERROR: identifier "KBUILD_MODNAME" is undefine

My environment: Ubuntu 18.04, kernel: linux-5.3.0-53 vscode: lastest
Command for fixing linux/module.h not find asm/xxx.h
cd /usr/src/linux-headers-5.3.0-53/include
sudo ln -s asm-generic/ asm
My c_cpp_properties.json
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/include",
"/usr/local/include",
"/usr/src/linux-headers-5.3.0-53/include",
"/usr/src/linux-headers-5.3.0-53-generic/include",
"/usr/src/linux-headers-5.3.0-53/arch/x86/include",
"/usr/src/linux-headers-5.3.0-53/include/uapi",
"/usr/lib/gcc/x86_64-linux-gnu/7.5.0/include"
],
"defines": [
"__GNUC__",
"__KERNEL__"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu11",
"cppStandard": "gnu++14",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}
My hello_module.c, a simple Linux kernel module program.
//a simple linux kernel module program.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL"); //error here
static int hello_init(void){
printk(KERN_ALERT "hello world\n");
return 0;
}
static void hello_exit(void){
printk(KERN_ALERT "goodbye world\n");
}
module_init(hello_init);
module_exit(hello_exit);
then ERROR:
identifier "KBUILD_MODNAME" is undefined
How to fix? Please help me..
KBUILD_MODNAME is automatically defined by the Makefile when you build your kernel module, so you will not find it anywhere in the kernel header files.
To stop vscode from complaining about undefined KBUILD_MODNAME identifier, just add a dummy definition to your c_cpp_properties.json file in the "defines" section
"defines": [
"KBUILD_MODNAME=\"hello_module\"",
"__GNUC__",
"__KERNEL__"
],
That should make vscode happy =)
The value you define for KBUILD_MODNAME does not really matter, since it is automatically defined during the make process.
I have not understood if this is your only problem, or if you also have problems to compile the module. If yes let me know and we will figure out how to solve that too!

cannot open source file "node.h" in hello.cc

Node Version:v12.1.0
Platform:Mac osx
node-gyp:v5.0.3
I don't know if it's a problem or just a personal question 。as a nodejs addons beginner,I write a
hello.cc file,which as below:
#include <node.h>
#include <v8.h>
using namespace v8;
// 实现􏵹定义的方法
Handle<Value> SayHello(const Arguments &args)
{
HandleScope scope;
return scope.Close(String::New("Hello world!"));
}
// 给传入的目􏵺对象􏱭加sayHello()方法 void Init_Hello(Handle<Object>target) {
target->Set(String::NewSymbol("sayHello"),FunctionTemplate::New(SayHello)->GetFunction());
// 调用NODE_MODULE()方法将注􏵻方法定义􏵼内存中 NODE_MODULE(hello, Init_Hello)
and my binding.gyp is like this:
{
'targets': [
{
'target_name': 'hello', 'sources': [
'src/hello.cc'],
'conditions': [['OS == "mac"',
{
}
]],
"include_dirs": [
"<!(node -e \"require('nan')\")"
]
}]
}
but the source code show Squiggles
and when I run node-gyp configure build
error shows:
all right version problem.
use nan.h fixed
https://github.com/nodejs/nan

node-gyp ignores (c++17) cflag

I try to configure & build a node.js C++ addon with this
binding.gyp file:
{
"targets": [
{
"target_name": "addon",
"sources": [ "addon.cpp" ],
"cflags": [
"-std=c++17"
]
}
]
}
But when I run node-gyp configure and node-gype rebuild
I always get messages like
warning: ‘if constexpr’ only available with -std=c++17 or -std=gnu++17
The build also fails, because I really depend on these c++17 features. What am I doing wrong?
cflags cflags_cc was not working for me, but with the setting in VCCLCompilerTool it works (on Windows):
{
'targets': [
{
'target_name': 'test-napi-native',
'sources': [ 'src/test_napi.cc' ],
'include_dirs': ["<!#(node -p \"require('node-addon-api').include\")"],
'dependencies': ["<!(node -p \"require('node-addon-api').gyp\")"],
'cflags': [ '-fno-exceptions' ],
'cflags_cc': [ '-fno-exceptions' ],
'xcode_settings': {
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'CLANG_CXX_LIBRARY': 'libc++',
'MACOSX_DEPLOYMENT_TARGET': '10.7'
},
'msvs_settings': {
'VCCLCompilerTool': { "ExceptionHandling": 1, 'AdditionalOptions': [ '-std:c++17' ] }
}
}
]
}
Using "cflags_cc" (instead of "cflags") works.
This solved the problem.
The default is against your will
node-gyp has default settings.
argv.push('-I', addonGypi)
argv.push('-I', commonGypi)
argv.push('-Dlibrary=shared_library')
argv.push('-Dvisibility=default')
argv.push('-Dnode_root_dir=' + nodeDir)
if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
argv.push('-Dnode_exp_file=' + nodeExpFile)
if (process.platform === 'os390' && zoslibIncDir) {
argv.push('-Dzoslib_include_dir=' + zoslibIncDir)
}
}
argv.push('-Dnode_gyp_dir=' + nodeGypDir)
// Do this to keep Cygwin environments happy, else the unescaped '\' gets eaten up,
// resulting in bad paths, Ex c:parentFolderfolderanotherFolder instead of c:\parentFolder\folder\anotherFolder
if (win) {
nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\')
}
argv.push('-Dnode_lib_file=' + nodeLibFile)
argv.push('-Dmodule_root_dir=' + process.cwd())
argv.push('-Dnode_engine=' +
(gyp.opts.node_engine || process.jsEngine || 'v8'))
You need to override the default settings described in node-gyp/addon.gypi and node/common.gypi’s cflags (C & C++), cflags_cc (C++), ldflags (Linux), msvs_settings (Windows), and xcode_settings (OS X). All of them.
In your case, you only set the cflags. So, other default settings were left not overridden and thus in effect.
Specifically, you’d want to override the default settings about:
the C++ standard to conform,
cflags_cc
msvs_settings.VCCLCompilerTool.AdditionalOptions
xcode_settings.CLANG_CXX_LANGUAGE_STANDARD
floating point arithmetics,
msvs_settings.VCCLCompilerTool.FloatingPointModel
exceptions,
cflags_cc
msvs_settings.VCCLCompilerTool.ExceptionHandling
xcode_settings.GCC_ENABLE_CPP_EXCEPTIONS
xcode_settings.GCC_ENABLE_CPP_RTTI
optimization,
the warning level,
et cetera.
If you don’t, unintented default settings might be applied.
Why it defaults to this
Because the Node.js executable is built with the settings and node-gyp adopted the settings for the default settings for unknown reasons.
From the nodejs/node-gyp issue #26 — “Overriding default flags”:
edhemphill: Does anyone know why -fno-rtti was used as a default? Any particular reason?
TooTallNate: #edhemphill node-gyp uses the same configuration as when node itself it built, so the answer is because node itself doesn’t need rtti.

Unable to use helper classes within unit tests of a bundled aurelia app. RequireJS Configuration?

Summary
Using the aurelia cli and the default tasks that are included, I am unable to leverage helper classes that are located within the test folder in my unit tests.
Details
Starting with the sample app created with au new, I have a contrived helper class located within 'test/util/helper.ts':
export class Helper {
Property : string;
}
This class is imported by the test/unit/app.spec.ts file:
import {App} from '../../src/app';
import {Helper} from "../util/helper";
describe('the app', () => {
it('says hello', () => {
let h = new Helper();
h.Property = "Testing";
expect(h.Property).toBe("Testing");
expect(new App().message).toBe('Hello World!');
});
});
Approach #1 - Bundling
I have modified the aurelia.json file in a few places:
Change the source of the typescript compiler to include files under the test folder
"transpiler": {
"id": "typescript",
"displayName": "TypeScript",
"fileExtension": ".ts",
"dtsSource": [
"./typings/**/*.d.ts",
"./custom_typings/**/*.d.ts"
],
"source": ["src\\**\\*.ts","test\\**\\*.ts"]
},
Modify the app-bundle to exclude any file from the test folder
{
"name": "app-bundle.js",
"source": {
"include": [
"[**/*.js]",
"**/*.{css,html}"
],
"exclude": [
"**/test/**/*"
]
}
},
Add a new bundle (test-util-bundle), which includes files from the test\util folder and excludes files within the src and test/unit folders
{
"name": "test-util-bundle.js",
"source": {
"include": [
"[**/*.js]"
],
"exclude": [
"**/src/**/*",
"**/test/unit/**/*"
]
}
},
After bundling the app with 'au build', I have three bundles (app/vendor/test-util), with the test-util-bundle.js bundle defining the helper class like this:
define('../test/util/helper',["require", "exports"], function (require, exports) {
"use strict";
var Helper = (function () {
function Helper() {
}
return Helper;
}());
exports.Helper = Helper;
});
I suspect this is the root of the problem, but not that familiar with RequireJS.
When I do run 'au test' the test fails with the following error:
11 10 2016 12:05:24.606:DEBUG [middleware:source-files]: Fetching C:/git/aurelia-cli-testing/test/test/util/helper
11 10 2016 12:05:24.608:WARN [web-server]: 404: /base/test/test/util/helper
Chrome 53.0.2785 (Windows 7 0.0.0) ERROR
Uncaught Error: Script error for "C:/git/aurelia-cli-testing/test/test/util/helper", needed by: C:/git/aurelia-cli-testing/test/util/helper
http://requirejs.org/docs/errors.html#scripterror
at C:/git/aurelia-cli-testing/scripts/vendor-bundle.js:3763
Note:
This works fine if I move the helper.ts file under the src tree (as done here). This is all available here if you would like to see the behavior.
Approach #2 - Without Bundling of utility class
Modify karma.conf.js
let testSrc = [
{ pattern: project.unitTestRunner.source, included: false },
{ pattern: "test/util/**/*.ts", included: false },
'test/aurelia-karma.js'
];
...
preprocessors: {
[project.unitTestRunner.source]: [project.transpiler.id],
["test/util/**/*.ts"]: [project.transpiler.id]
},
With this modification (no bundling of the utility class) karma produces the following error:
18 10 2016 16:56:59.151:DEBUG [middleware:source-files]: Fetching C:/git/aurelia-cli-testing/test/util/helper
18 10 2016 16:56:59.152:WARN [web-server]: 404: /base/test/util/helper
Chrome 53.0.2785 (Windows 7 0.0.0) ERROR
Uncaught Error: Script error for "C:/git/aurelia-cli-testing/test/util/helper", needed by: C:/git/aurelia-cli-testing/test/unit/app.spec.js
http://requirejs.org/docs/errors.html#scripterror
at C:/git/aurelia-cli-testing/scripts/vendor-bundle.js:3763
Thanks for reading, any help would be greatly appreciated!
With the help of an Aurelia team member, a small modification to the aurelia-karma.js file that is distributed with the aurelia cli fixes the issue:
The normalizePath function should be modified to append '.js' where applicable:
function normalizePath(path) {
var normalized = []
var parts = path
.split('?')[0] // cut off GET params, used by noext requirejs plugin
.split('/')
for (var i = 0; i < parts.length; i++) {
if (parts[i] === '.') {
continue
}
if (parts[i] === '..' && normalized.length && normalized[normalized.length - 1] !== '..') {
normalized.pop()
continue
}
normalized.push(parts[i])
}
//Use case of testing source code. RequireJS doesn't add .js extension to files asked via sibling selector
//If normalized path doesn't include some type of extension, add the .js to it
if(normalized.length > 0 && normalized[normalized.length-1].indexOf('.') < 0){
normalized[normalized.length-1] = normalized[normalized.length-1] + '.js';
}
return normalized.join('/')
}
I had to do the following:
1. update the aurelia-project/aurelia.json file. add this
"unitTestRunnerUtils": {
"id": "karmaUtils",
"displayName": "Karma",
"source": "test\\utils\\**\\*.js" },
Then in the karma.conf.js file updated these two places.
let testSrc = [ { pattern: project.unitTestRunner.source, included:
false }, { pattern: project.unitTestRunnerUtils.source, included:
false}, 'test/aurelia-karma.js' ];
and
preprocessors: {
[project.unitTestRunner.source]: [project.transpiler.id],
[project.unitTestRunnerUtils.source]: [project.transpiler.id]
},
And then it worked...
Here is the example project on github.
https://github.com/duranmg/demo-aurelia-testing

Resources