My goal is to make a module which provides access to the last time of user interaction (Client side app - not a server app). The Windows API has a function called GetLastInputInfo (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646302(v=vs.85).aspx). Below is the code which should load the time information into last_input and it returns 0/1 for failure/success. Unfortunately, it fails every time.
Addon code:
#include <node.h>
#include <v8.h>
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
using namespace v8;
Handle<Value> TimeSinceInput(const Arguments& args) {
HandleScope scope;
LASTINPUTINFO last_input;
if (::GetLastInputInfo(&last_input)) {
return scope.Close(String::New("Success!"));
}
else {
return scope.Close(String::New("Failed for some reason!"));
}
}
void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("time_since_input"), FunctionTemplate::New(TimeSinceInput)->GetFunction());
}
NODE_MODULE(addon, init)
Any thoughts?
LASTINPUTINFO structure has member cbSize, that should be initialized:
The size of the structure, in bytes. This member must be set to sizeof(LASTINPUTINFO).
It's a common way for versioning in Windows API.
Related
I'm trying to write a c++/cli wrapper for IO Industries Core2 DVR, which will then be used by LabView. The company provided a SDK with with all the headers (written in c++) and boost library. I've managed to build a wrapper that builds and LabView is able to see the function through the .net pallet.
// ManagedProject.h
#pragma once
#include "core_api_helper.h"
#include "core_api.h"
using namespace System;
using namespace CoreApi;
namespace ManagedProject {
//Setup class
public ref class Setup
{
private:
public:
unsigned int initializeTest();
};
}
// This is the DLL Wrapper.
#include "stdafx.h"
#include "ManagedProject.h"
#include "core_api_helper.h"
#include "core_api.h"
#include "resource.h"
using namespace CoreApi;
using namespace Common;
using namespace ManagedProject;
//Global handles
//A handle to the Core Api
InstanceHandle g_hApi;
//A handle to the Core Api Device Collection
DeviceCollectionHandle g_hCoreDeviceCollection;
unsigned int Setup::initializeTest()
{
try
{
//Initialize the Core API (must be called before any other Core API functions)
//Returns a handle to the Core Api
g_hApi = Instance::initialize();
// get a collection of Core devices
g_hCoreDeviceCollection = g_hApi->deviceCollection();
unsigned int deviceCount = g_hCoreDeviceCollection->deviceCount();
return deviceCount;
}
catch (GeneralException& e)
{
e.what();
return 3;
}
}
However when I run LabView through Visual studio 2015 in debug mode I run into the problem below, and what is returned to LabView is the 3 from the catch block.
First break in debug mode (NULL ptr)
NOTE: InstanceHandle is a shared_ptr
As can be seen the variable is a NULL pointer, the same thing happens for the g_hCoreDeviceCollectoin as well. I think I need to Instantiate it with the new command but am a little unsure as InstanceHandle is a shared_ptr.
Any help would be much appreciated
The C++/CLI has great feature called mixed mode. You can uses both managed and native data types in the same code (in the same C++/CLI class). Try to use object from that SDK written in C++ directly in your wrapper.
I would like to call a nodejs callback from within my asynchronous addon function. I have seen the synchronous example (here)
and I am using a wonderful asynchronous example (here) as a starting base.
However, when I try to execute a callback that was given to the c++ AsyncWorker child class, I get a Segmentation fault.
Here is my code:
#include <nan.h>
#include <functional>
#include <iostream>
#include <exception>
using namespace Nan;
using namespace v8;
using namespace std;
class ScriptWorker : public AsyncWorker {
public:
ScriptWorker(Callback *callback, const std::map<std::string, Callback*>)
: AsyncWorker(callback), script(script), cbs(cbs) {}
~ScriptWorker() {}
void Execute () {
// ------------------------
// Segmentation fault after
// ------------------------
Local<Value> argv[] = {
New<v8::Number>(id)
};
// -------------------------
// Segmentation fault before
// -------------------------
cbs["getUser"]->Call(1, argv);
}
private:
std::string script;
std::map<std::string, Callback*> cbs;
};
NAN_METHOD(Method) {
Local<Object> array = info[0]->ToObject();
Callback *callback = new Callback(info[1].As<Function>());
// Build up callbacks passed in from javascript.
// Will be a dynamic loop, but for now, hard code the one getUser example.
std::map<std::string, Callback*> cbs;
cbs.insert(std::pair<std::string, Callback*>("getUser",
new Callback(
array->Get(
v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "getUser")
).As<Function>()
)
));
AsyncQueueWorker(new ScriptWorker(callback, cbs));
}
NAN_MODULE_INIT(Init) {
Nan::Set(target, Nan::New<String>("hello").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(Method)).ToLocalChecked());
}
NODE_MODULE(hello, Init)
My questions:
Should I not use Nan's AsyncWorker and instead roll my own?
How do I setup the Execute function to call into Javascript?
EDIT:
See this repo:
https://github.com/xavero/node_addon_sample
it has a sample on how to work with callback functions and emitting events from C land.
You should not call v8/Nan functions in your Execute method of ScriptWorker, or you will get segment faults. Override the HandleOKCallback function to use the javascript callback.
To call from the javascript, in your c++ addon:
NAN_MODULE_INIT(Init) {
Nan::Set(target, Nan::New("myJsFunctionName").ToLocalChecked(),
Nan::GetFunction(Nan::New<FunctionTemplate>(Method)).ToLocalChecked());
}
NODE_MODULE(anyNameHere, Init)
And in your javascript:
// run "npm install bindings --save" in console first
var addon = require('bindings')('NativeExtension');
addon.myJsFunctionName({ foo: "bar"}, (arg1,arg2) => console.log(`${arg1} - ${arg2}`))
Here is the error I am receiving when running the project that I am using the DLL in:
The odd thing is that this was working at one point. I took a break from this project for a while and now it is not working. Not much has changed besides changing a couple of the parameters.
My setup includes a project in which I build the DLL. This project is then used in a solution with another project that I use to test it. I followed this example: https://msdn.microsoft.com/en-us/library/ms235636.aspx in which I also followed the first time and had it working, now it has stopped.
After realizing it seems to be only one of the functions that is causing the problem I have removed all of the extra code, tried renaming the function, removing everything in it and it is STILL not working.
You can see the function definitions and signatures to see how I am attempting to get this to work below
I have also tried using the "SCOREINTERFACECPP" macro I created on the function instead of the class and I get the same error.
In the project I am testing it in I added the DLL project as a reference and a dependent project, then imported the header file. The other functions I have in the dll (that I have removed from this code for simplicity sake) seem to be working.
Header:
#ifdef SCOREINTERFACECPP_EXPORTS
#define SCOREINTERFACECPP __declspec(dllexport)
#else
#define SCOREINTERFACECPP __declspec(dllimport)
#endif
#include <time.h>
#include <queue>
namespace ScoreInterfaceCPP
{
class SCOREINTERFACECPP ScoreInterface
{
public:
ScoreInterface();
~ScoreInterface();
static void SubmitLogin(const std::string &displayName, const std::string &password);
static void Shutdown();
static SIEvent* GetNextEvent();
static void ClearEvents();
static int GetEventCount();
private:
static std::queue< SIEvent* > mSIEvents;
static bool mGameIsAuthorized;
static std::string mGameName;
static std::string hexedKey;
static std::wstring mAddress;
static void SubmitEventString(std::string eventString);
static int SubmitWithNewThread(void* data);
static void PostMessage(std::string data, std::string iv);
};
}
Source:
#include <sstream>
#include <SDL/SDL_thread.h>
#include <boost/tokenizer.hpp>
#include "ScoreInterfaceCPP.h"
#include "Network.h"
using namespace ScoreInterfaceCPP;
/*
ScoreInterfaceCPP.h
Handles the sending and receiving of events.
*/
ScoreInterface::ScoreInterface()
{
}
ScoreInterface::~ScoreInterface()
{
}
void ScoreInterface::SubmitLogin(const std::string &displayName, const std::string &password)
{
}
void ScoreInterface::SubmitEventString(std::string eventString)
{
}
int ScoreInterface::SubmitWithNewThread(void* data)
{
return 0;
}
SIEvent* ScoreInterface::GetNextEvent()
{
return NULL;
}
int ScoreInterface::GetEventCount()
{
return 0;
}
void ScoreInterface::ClearEvents()
{
}
void ScoreInterface::Shutdown()
{
}
Test file:
#include "ScoreInterfaceCPP.h"
using namespace ScoreInterfaceCPP;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
ScoreInterface si = ScoreInterface();
si.SubmitLogin("noplayer", "nopassword");
return 0;
}
In my experience, usually problems of this type come with two things you should check (assuming the DLL was built successfully):
Check that the DLL being loaded at runtime is the correct version.
Ensure that the function in question is actually exported.
For the first issue, you can use a utility such as Process Explorer and look at the DLL handles that are loaded for your running exectuable. If you are using Visual C++, you can also look at the Output Window listing of the DLL's that are loaded, and ensure that the version you're using is being loaded.
Many times during development, you may have several (either by accident or by design) versions of your DLL lying in a directory that is accessible by Windows (see DLL Search Order), and thus an old or different version of your DLL is being loaded when you run your application.
For the second issue, there is dumpbin.exe, but I find the Dependency Walker a little more friendly to use. These utilities will show you the functions that are exported from the DLL.
If it is discovered that the function was not exported, then you need to rebuild your DLL, ensuring that __declspec(dllexport) has been used on the function or class you're exporting.
I am writing a NodeJS addon where I use a C library that lets you register a callback at certain events. When the callback is fired I want to call a NodeJS callback function. The problem is that in my C callback function I get a segmentation fault when trying to do anything V8 related, like creating a HandleScope.
In test.js:
...
myaddon.register(function(data) {
console.log("data: " + JSON.stringify(data));
});
...
In test.c:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <node.h>
#include <v8.h>
using namespace v8;
void WINAPI myEvent(int num, void * context) {
HandleScope scope; // Segmentation fault here!
Local<Function> * cb = (Local<Function>*)(context);
Local<Object> obj = Object::New();
obj->Set(String::NewSymbol("id"), Number::New(num));
const int argc = 1;
Local<Value> argv[argc] = { obj };
(*cb)->Call(Context::GetCurrent()->Global(), argc, argv);
sleep(1);
}
Handle<Value> RegisterEvent(const Arguments& args) {
HandleScope scope;
Local<Function> cb = Local<Function>::Cast(args[0]);
int callbackId = registerEvent((Event)&myEvent, &cb );
printf("callback id: %i\n", callbackId);
init();
return scope.Close(Integer::New(callbackId));
}
void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("register"),
FunctionTemplate::New(RegisterEvent)->GetFunction());
}
NODE_MODULE(test, init)
EDIT: Updated with real code.
EDIT: I just changed the title of this issue since the problem is probably that my callback function can't access the V8 Context. Since I get a segmentation fault when creating HandleScope instance I can't see what else it might be. In addition to this question I AM trying to find the answer in the V8 documentation, but it is huge and I don't have that much time to test and investigate.
Your handler function myEvent() must be called in V8 thread. If not, you have to post the event notification into the V8 thread:
https://stackoverflow.com/a/15701160/1355844
https://stackoverflow.com/a/22946062/1355844
It appears that you might have forgotten to create a HandleScope for your variable. This should work for you.
void callbackFunc() {
HandleScope scope;
Local<Object> obj = Object::New();
}
I'm currently developing a simulator that runs on a server and should display data in the browser.
For serving files, communication and things like that, I'd like to use Node.js. But, I'm not sure if it will perform as well as I'd want it to in the computation department, so I would like to develop the simulation part in C++.
The simulation is divided into separate "worlds", which all start with some initial parameters.
What is the best way to do this?
Well, V8 allows for C++ code to be called from JavaScript.
So you can have 3 parts of your code:
Normal C++, unaware of node.js and V8. This would be where World is.
Glue node.js/V8-C++ code, allowing JS to "see" parts of your World class.
Normal JavaScript code, which communicates with the C++ side via the "glue" layer
First, understand how V8 and C++ communicate. Google provides a guide for this: https://developers.google.com/v8/embed
Then, you need node.js specific glue. See http://www.slideshare.net/nsm.nikhil/writing-native-bindings-to-nodejs-in-c and http://syskall.com/how-to-write-your-own-native-nodejs-extension
From the slideshare link above:
#include <v8.h>
#include <node.h>
using namespace v8;
extern "C" {
static void init(Handle<Object> target) {}
NODE_MODULE(module_name, init)
}
We can expand that into something closer to what you want:
src/world.h
#ifndef WORLD_H_
#define WORLD_H_
class World {
public:
void update();
};
extern World MyWorld;
#endif
src/world.cpp
#include "world.h"
#include <iostream>
using std::cout;
using std::endl;
World MyWorld;
void World::update() {
cout << "Updating World" << endl;
}
src/bind.cpp
#include <v8.h>
#include <node.h>
#include "world.h"
using namespace v8;
static Handle<Value> UpdateBinding(const Arguments& args) {
HandleScope scope;
MyWorld.update();
return Undefined();
}
static Persistent<FunctionTemplate> updateFunction;
extern "C" {
static void init(Handle<Object> obj) {
v8::HandleScope scope;
Local<FunctionTemplate> updateTemplate = FunctionTemplate::New(UpdateBinding);
updateFunction = v8::Persistent<FunctionTemplate>::New(updateTemplate);
obj->Set(String::NewSymbol("update"), updateFunction->GetFunction());
}
NODE_MODULE(world, init)
}
demo/demo.js
var world = require('../build/Release/world.node');
world.update();
wscript
def set_options(opt):
opt.tool_options("compiler_cxx")
def configure(conf):
conf.check_tool("compiler_cxx")
conf.check_tool("node_addon")
def build(bld):
obj = bld.new_task_gen("cxx", "shlib", "node_addon")
obj.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall"]
# This is the name of our extension.
obj.target = "world"
obj.source = "src/world.cpp src/bind.cpp"
obj.uselib = []
On Linux shell, some setup:
node-waf configure
To build, run:
node-waf
To test:
node demo/demo.js
Output:
Updating World