Skip to content

Instantly share code, notes, and snippets.

@issacg
Last active December 13, 2016 16:30
Show Gist options
  • Save issacg/a64a8805b0731537e495d57ab39acf3a to your computer and use it in GitHub Desktop.
Save issacg/a64a8805b0731537e495d57ab39acf3a to your computer and use it in GitHub Desktop.
nodejs c++/cli bug
{
"targets": [{
"target_name": "clrtest",
"sources": ["main.cc"],
"include_dirs" : [
"<!(node -e \"require('nan')\")"
],
"msvs_settings": {
"VCCLCompilerTool": {
"RuntimeTypeInfo": "true"
}
},
"msbuild_settings": {
"ClCompile": {
"CompileAsManaged": "true",
"ExceptionHandling": "Async",
}
},
"configurations" : {
"Debug": {
"msbuild_settings": {
"ClCompile": {
"AdditionalOptions": [ "/MDd", "/Od" ]
}
}
}
},
"defines":["UNICODE","_UNICODE"]
}]
}
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#pragma managed(push, off)
#include <node.h>
#include "nan.h"
#pragma managed(pop)
#include <vcclr.h>
#using <System.dll>
#using <System.Core.dll>
using namespace System;
using namespace System::Management;
using namespace System::Text;
using v8::FunctionTemplate;
using v8::Handle;
using v8::Object;
using v8::String;
using v8::Number;
using v8::Boolean;
using v8::Value;
ref class OSClass
{
private:
int _value;
public:
OSClass(int value) : _value(value) {}
LPCWSTR name() {
System::String ^tempClr = System::String::Concat(Convert::ToString(Environment::OSVersion), System::String::Concat(" ", Convert::ToString(_value)));
return (LPCWSTR)(Runtime::InteropServices::Marshal::StringToHGlobalAuto(tempClr).ToPointer());
}
};
class OSClassV8 : public Nan::ObjectWrap {
private:
gcroot<OSClass^> _c;
static NAN_METHOD(New) {
if (info.IsConstructCall()) {
OSClassV8* o = new OSClassV8(Nan::To<int32_t>(info[0]).FromJust());
o->Wrap(info.This());
info.GetReturnValue().Set(info.This());
}
else {
const int argc = 1;
v8::Local<v8::Value> argv[argc] = { info[0] };
v8::Local<v8::Function> cons = Nan::New(constructor());
info.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
public:
explicit OSClassV8(int value) {
_c = gcnew OSClass(value);
}
inline gcroot<OSClass^> c() const {
return _c;
}
static NAN_MODULE_INIT(Init) {
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("OSClassContainer").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked());
Nan::Set(target, Nan::New("OSClassContainer").ToLocalChecked(),
Nan::GetFunction(tpl).ToLocalChecked());
}
static inline Nan::Persistent<v8::Function> & constructor() {
static Nan::Persistent<v8::Function> my_constructor;
return my_constructor;
}
};
class OSClassV8Worker : public Nan::AsyncWorker {
private:
LPCWSTR string;
gcroot<OSClass^> c;
public:
OSClassV8Worker(Nan::Callback* callback, gcroot<OSClass^> c): Nan::AsyncWorker(callback), string(0), c(c) {}
~OSClassV8Worker() {
if (this->string) {
Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr((void*)this->string));
}
}
void Execute() {
try {
string = c->name();
}
catch (System::Exception^ e) {
CHAR buf[1024];
LPWSTR str = (LPWSTR)(Runtime::InteropServices::Marshal::StringToHGlobalAuto(e->ToString()).ToPointer());
wcstombs(buf, str, 1024);
this->SetErrorMessage(buf);
Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr((void*)str));
}
}
void HandleOKCallback() {
Nan::HandleScope scope;
v8::Local<Value> argv[] = {
Nan::Null(),
Nan::New<v8::String>((uint16_t const*)this->string).ToLocalChecked()
};
callback->Call(2, argv);
}
};
NAN_METHOD(GetNameAsync) {
Nan::HandleScope scope;
OSClassV8* obj;
Nan::MaybeLocal<v8::Object> maybe1 = Nan::To<v8::Object>(info[0]);
if (info.Length() != 2) {
return Nan::ThrowError("Invalid arguments");
}
if (maybe1.IsEmpty()) {
return Nan::ThrowError("Invalid OSClassContainer");
}
if (!info[1]->IsFunction()) {
return Nan::ThrowError("Missing callback");
}
obj = Nan::ObjectWrap::Unwrap<OSClassV8>(maybe1.ToLocalChecked());
Nan::Callback *callback = new Nan::Callback(info[1].As<v8::Function>());
Nan::AsyncQueueWorker(new OSClassV8Worker(callback, obj->c()));
}
#pragma managed(push, off)
NAN_MODULE_INIT(Init) {
OSClassV8::Init(target);
Nan::SetMethod(target, "GetName", GetNameAsync);
}
NODE_MODULE(clrtest, Init)
#pragma managed(pop)
"use strict";
const clrtest = require('./build/Release/clrtest.node');
let obj = new clrtest.OSClassContainer(42);
clrtest.GetName(obj, function(err, res) {
if (err)
return console.error(err);
console.log(res);
});
const webpack = require('webpack');
module.exports = {
entry: './main.js',
target: 'node',
output: {
filename: 'bundle.js',
path: './build'
},
module: {
loaders: [
{ test: /\.node$/, loader: "node-loader" }
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment