I'm creating a node.js addon, which has bunch of classes. I want to organize them in a hierarchical namespace. If I were doing this in Javascript it would look like this
var com = function() {};
com.example = function() {};
com.example.Person = function () {};
var p = new com.example.Person();
I'm using Nan to write my node.js binding. To achieve the above result I've written code as follows:
com.h
namespace addon {
void init(Local<Object> exports);
}
com.cpp
void addon::init(Local<Object> exports)
{
addon::Example::Init(exports);
}
NODE_MODULE(com, com::init)
example.h
namespace addon {
class Example : public Nan::ObjectWrap {
static void Init(v8::Local<v8::Object> exports);
}
}
example.cpp
void addon::Example::Init(v8::Local<v8::Object> exports) {
// Prepare constructor template
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("example").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
addon::Person::Init(tpl);
constructor.Reset(tpl->GetFunction());
}
person.h
namespace addon {
class Person : public Nan::ObjectWrap {
static void Init(v8::Local<v8::FunctionTemplate> exports);
}
}
person.cpp
void addon::Person::Init(v8::Local<v8::FunctionTemplate> nmspace) {
Nan::HandleScope scope;
// Prepare constructor template
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("Person").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
// ...
constructor.Reset(tpl->GetFunction());
nmspace->Set(Nan::New("Person").ToLocalChecked(), tpl->GetFunction()); // XXXXXX
}
This code compiles and also successfully passes the tests when run. However I get a warning when the addon is loaded.
(node) v8::FunctionTemplate::Set() with non-primitive values is deprecated
(node) and will stop working in the next major release.
It prints a stack trace. The top of this trace is at the line marked XXXXXX.
If this is not the recommended way to define a FunctionTemplate as a member of another FunctionTemplate, then what's the right way to achieve it? Any ideas?
I found an easy way to do this. It occured to me that I could achieve the same thing with the following Javascript code.
var com = {};
com.example = {};
com.example.Person = function () {};
var p = new com.example.Person();
So I found that it's totally unnecessary to define a ObjectWrap class for Example. Instead I defined it as a simple object
v8::Isolate *isolate = v8::Isolate::GetCurrent();
v8::Handle<Object> example = v8::Object::New(isolate);
and then passed it to Person::Init() like this
void addon::Person::Init(v8::Local<v8::Object> nmspace) {
// ...
nmspace->Set(Nan::New("Person").ToLocalChecked(), tpl->GetFunction());
}
The resulting code works without any warnings or errors.
Related
here is a sample source code of vala for creating a simple GTK application from elementary os website
public class Examples.Application : Gtk.Application {
public Application () {
Object (
application_id: "org.valadoc.examples",
flags: ApplicationFlags.FLAGS_NONE
);
}
protected override void activate () {
var application_window = new Gtk.ApplicationWindow (this);
application_window.show_all ();
}
public static int main (string[] args) {
var app = new Application ();
return app.run (args);
}
}
i dont understand th object in this code? what is it? is it an object ? if its an object so why it has not new keword and not instanciated?
The Object() you see there in the constructor is a Vala-specific syntax called: GObject-style construction. It allows you to set your properties all at once.
This allows you to work with GObject's so-called "construct properties": properties which can be set during construction (sometimes they can even only exclusively be set during construction).
I created a wrapper around DryIoC container which is just a class that delegates tasks to DryIoC methods ( for example, myContainer.Register<T>() will call dryIoC.Register<T>() ). the goal is just to hide the real implementation behind my interface so I can switch to another DI container if I wanted to.
All works fine, but I faced a problem today when I tried to work with Scopes likes in this example code taken from here
// example using DryIoC
var container = new Container();
container.Register<B>();
using (var scope = container.OpenScope())
{
var a = new A();
scope.UseInstance(a); // Scoped
scope.Resolve<B>(); // will inject `a`
}
var anotherA = new A();
container.UseInstance(anotherA); // Singleton
container.Resolve<B>(); // will inject `anotherA`
my naive wrapper implementation was to create another constructor that accepts an instance of DryIoC container and do it like this :
// My Wrapper class
public Infrastructure.IMyContainer OpenScope()
{
return new MyContainer(dryIoC.OpenScope());
}
my understanding is that dryIoC.OpenScope() returns a new instance of the container, so all I had to do is save this instance internally and use it to resolve my classes. but that implementation didn't work for me, here my unit test :
[Test]
public void OpenScope_Creates_A_Scoped_Container()
{
var _container = new MyContainer();
_container.Register<IMyInterface, MyImpl>();
_container.Register<MyDependingClass>();
MyDependingClass cls1 = null;
MyDependingClass cls2 = null;
var dep = new MyImpl();
using (var scope = _container.OpenScope())
{
scope.UseInstance(dep);
cls1 = scope.Resolve<MyDependingClass>(); // this should inject 'dep' instance created in the line before the creation of the scope
}
cls2 = _container.Resolve<MyDependingClass>(); // this should inject another instance.
cls1.Dep.ShouldBeSameAs(dep); // cls1 was resolved in the scope, so it should get 'dep' instance
cls1.Dep.ShouldNotBeSameAs(cls2.Dep); // cls2.Dep should be different
}
// stub classes/interfaces
class MyDependingClass
{
public MyDependingClass(IMyInterface dep)
{
Dep = dep;
}
public IMyInterface Dep { get; }
}
class MyImpl : IMyInterface { }
but this test fails at cls1.Dep.ShouldBeSameAs(dep); telling me that the two instances of IMyInterface was different !!!
Am I missing something ??
How do you get callbacks running in haxe 3 that are passed by another class?
I'm trying to pass a callback function to a class, but I'm getting an error
public static var onFocusCallback:Dynamic;
public static function triggerFocus():Void
{
onFocusCallback.bind();
}
the error I get is
[Fault] exception, information=ReferenceError: Error #1069: Property bind not found on builtin.as$0.MethodClosure and there is no default value.
Try not to use Dynamic if possible. It can trigger weird errors like that one.
The way to use a callback is like this http://try.haxe.org/#60f45
class Test {
static function main() {
onFocusCallback = function() {
trace("focus");
}
triggerFocus();
}
// Try not to use Dynamic
//public static var onFocusCallback:Dynamic;
// If you don't know the type of the function, you can use this:
//public static var onFocusCallback:haxe.Constraints.Function;
// But it's always better to give a concrete type like:
public static var onFocusCallback:Void->Void;
public static function triggerFocus():Void
{
if(onFocusCallback != null) onFocusCallback();
}
}
the other solution I got to work, within minutes of posting question, was to use Reflect
Reflect.callMethod(null, onFocusCallback, []);
I'm trying to use TypeScript to create a common library for a set of related web sites. I started off code like this:
module Lib {
export module Tools {
export class Opener {
public Path: string;
public static Open(): boolean { /* ... */ }
}
export class Closer { /* ... */ }
}
export module Controls {
export class InfoDisplay { /* ... */ }
export class Logon { /* ... */ }
}
export module Entities {
export class BigThing { /* ... */ }
export class LittleThing { /* ... */ }
}
}
var Initial: boolean = Lib.Tools.Opener.Open();
var CustomOpener: Lib.Tools.Opener = new Lib.Tools.Opener();
This worked quite well and allowed me to use some of TypeScript's nice features, like static methods and namespaced class names. As the project has grown, however, the need to use a module system for dependency resolution has become clear. My problem is that I'm a RequireJS noob so I can't quite figure out how get preserve the desirable features mentioned above to work in my project once RequireJS is in the mix. Here's my best attempt so far (which, to save space, only shows the code trail for Opener):
// ---- Opener.ts --------------------------------------------------------
/// <reference path="../typings/requirejs/require.d.ts"/>
class Opener {
public Path: string;
public static Open(): boolean { /* ... */ }
}
export = Opener;
// ---- Tools.ts --------------------------------------------------------
/// <reference path="../typings/requirejs/require.d.ts"/>
import Opener = require("./Opener");
import Closer = require("./Closer");
class Tools {
public Opener: Opener = new Opener();
public Closer: Closer = new Closer();
}
export = Tools;
// ---- ReqLib.ts --------------------------------------------------------
/// <reference path="../typings/requirejs/require.d.ts"/>
import Tools = require("./Tools");
class ReqLib {
public Tools: Tools = new Tools();
}
export = ReqLib;
// ---- App.ts --------------------------------------------------------
import ReqLib = require("./ReqLib");
var RL: ReqLib = new ReqLib();
var Initial: boolean = RL.Tools.Opener.Open(); // <== red squiggles
var CustomerOpener: ReqLib.Tools.Opener = new ReqLib.Tools.Opener(); // <== red squiggles
Visual Studio doesn't like the last two lines. It can't see the static method in the first line and it just flat out doesn't like the second because it looks like instances are being used as types. It's also the more troubling case because TypeScript kind of needs to have types to work with.
In your code RL.Tools.Opener is resolving to new Opener(); The static public static Open() does not exist on an instance but instead exists on the class Opener, hence the compiler error.
Suggestion : don't make it static. There might be other suggestions but now you know the reason for the error.
UPDATE
for new ReqLib.Tools.Opener(); you need to do new ReqLib().Tools.Opener;
I'm working on a plugin that does device detection based on an external library.
This is what I have so far:
class Deetector {
// public $return_data;
/**
* Constructor
*/
public function __construct()
{
$this->EE =& get_instance();
$this->EE->load->add_package_path(PATH_THIRD.'/deetector');
$this->EE->load->library('detector');
$this->return_data = "";
}
public function deetector()
{
return $ua->ua;
}
public function user_agent()
{
return $ua->ua;
}
// ----------------------------------------------------------------
/**
* Plugin Usage
*/
public static function usage()
{
ob_start();
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
}
If I call {exp:deetector} I get no output in the template. If I call {exp:deetector:user_agent} I get Undefined variable: ua.
Ultimately I don't plan on setting up different functions for each of the variables that the Detector library returns but am just trying to get it to output something at the moment.
I had originally started doing this as an extension which added the Detector library's variables to the global variables array and that was working fine; it's only since trying to do it as a plugin that I've run into problems.
You haven't set $this->ua to anything. I assume it's a variable of the detector library you loaded, so you probably want to do something like this:
class Deetector {
public function __construct()
{
$this->EE =& get_instance();
// remove this line, it's probably not doing anything
// $this->EE->load->add_package_path(PATH_THIRD.'/deetector');
$this->EE->load->library('detector');
// note you use $this->return_data instead of "return blah" in the constructor
$this->return_data = $this->EE->detector->ua;
}
// remove this, you can't have both __construct() and deetector(), they mean the same thing
// public function deetector()
// {
// return $ua->ua;
// }
public function user_agent()
{
return $this->EE->detector->ua;
}
}
UPDATE:
I took a look at the Detector docs, and it doesn't follow normal library conventions (it defines the $ua variable when you include the file). For that reason you should ignore the standard EE load functions, and include the file directly:
class Deetector {
public function __construct()
{
$this->EE =& get_instance();
// manually include the detector library
include(PATH_THIRD.'/deetector/libraries/detector.php');
// save the local $ua variable so we can use it in other functions further down
$this->ua = $ua;
// output the user agent in our template
$this->return_data = $this->ua->ua;
}
}