Spidermonkey TypeError - spidermonkey

I've managed to integrate Spidermonkey into my C server side application on Linux.
Trying to create an object from javascript:
var obj = new MyObject();
obj.foo()
gives the following Error:
[error] test.js:22:TypeError: obj.foo is not a function
I'm probably missing something...Here is how MyObject defined:
//Class definition
static JSClass myobject_class = {
"MyObject", JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
JSCLASS_NO_OPTIONAL_MEMBERS
};
//Methods
static JSFunctionSpec myobject_funcs[] = {
JS_FS("foo", JS_foo, 0, 0),
};
//Static methods
static JSFunctionSpec myobject_funcs_static[] = {
JS_FS_END
};
//foo method
JSBool JS_foo(JSContext *cx, uintN argc, jsval *vpn) {
return JS_TRUE;
}
//Constructor
JSBool JS_myobject_ctor(JSContext *cx, uintN argc, jsval *vpn) {
JSObject *obj = JS_NewObjectForConstructor(cx, vpn);
JS_DefineFunctions(cx,obj,myobject_funcs);
return JS_TRUE;
}
//Init context
JSContext * context_init(size_t size,void* privateData) {
/* Create a context. */
jsContext = JS_NewContext(jsRuntime, 8192);
if (jsContext == NULL) return NULL;
.....
.....
.....
//myobject init
JSObject *my = JS_InitClass(jsContext, global, NULL, &myobject_class, JS_myobject_ctor, 0, NULL, NULL, NULL, myobject_funcs_static);
JS_DefineFunctions(jsContext, my, myobject_funcs);
return jsContext;
}

I was able to find some older example that included:
JS_SET_RVAL(cx, vpn, OBJECT_TO_JSVAL(obj));
in the constructor.
It worked as a charm.
//Constructor
JSBool JS_myobject_ctor(JSContext *cx, uintN argc, jsval *vpn) {
JSObject *obj = JS_NewObjectForConstructor(cx, vpn);
JS_DefineFunctions(cx,obj,myobject_funcs);
JS_SET_RVAL(cx, vpn, OBJECT_TO_JSVAL(obj));
return JS_TRUE;
}

Related

node-ffi - printing strings that return from C++ funcs

I have some class MyObject
MyObject * m_instance;
extern "C"
{
void createNew()
{
m_instance = new MyObject ("one", "two");
}
const char * getCharOne()
{
std::cout<< "one" <<m_instance->getFirstString().c_str()<<std::endl;
return m_instance->m_instance->getFirstString().c_str();
}
}
//example.js
var ffi = require('ffi');
var libm = ffi.Library('libExample', {
'createNew': ["void",[]],
'getCharOne' : ['string',[]],
});
libm.createNew();
var o = libm.getCharOne();
console.log(o);
i get the print inside the getCharOne function, but not from the console log.
Any help will be greatly appreciated

JNI doesn't initialize Class Obj with String

Below is my C and Java code. Java called function1 to collect a String and an integer and return them using ResultCollector object. The ResultCollector is an outer class, in other words, it is not nested inside the ResultCollecter class. Also, it has three constructors. I have other functions that are fine with a constructor with (IF)V signature. Also, the third constructor is not working as well (i.e. (II)V).
Java code is:
package user.directory;
public class ResultCollector {
private int err;
private float resVal;
private String resID;
/**
* Signature (IF)V
*/
public ResultCollector(int err, float value) {
this.err = err;
this.resVal = value;
}
/**
* Signature (II)V
*/
public ResultCollector(int err, int value) {
this.err = err;
this.resVal = (float) value;
}
/**
* Signature (ILjava/lang/;)V
*/
public ResultCollector(int err, char[] id) {
this.err = err;
this.resID = String.copyValueOf(id);
}
public String id() {
return resID;
}
public int err() {
return err;
}
public float value() {
return resVal;
}
public void setParam(int err, String id, float value) {
this.err = err;
this.resID = id;
this.resVal = value;
}
}
And C code is:
JNIEXPORT jobject JNICALL Java_project_function1(
JNIEnv *env, jobject obj, jint index) {
jint t;
char *id = C function to return string;
t = an error that is needed;
if (c == NULL)
// throw exception
return NULL;
jstring name = (*env)->NewStringUTF(env, id);
if (name == NULL)
// throw exception
return NULL;
jclass c = (*env)->FindClass(env,
"user/directory/ResultCollector");
jmethodID constr = (*env)->GetMethodID(env, c, "<init>", "(ILjava/lang/String;)V");
if (constr == NULL)
//cannot get the constructor correctly
return NULL;
jobject result = (*env)->NewObject(env, c, constr, t, name);
return result;
}
My question is: How I can initialize an outer class? Where does it go wrong in this code?
char[] is not the same as String. The signature for your constructor function should be (I[C)V ([ indicates an array, C is for char):
jmethodID constr = (*env)->GetMethodID(env, c, "<init>", "(I[C)V");
You will also need to pass a jcharArray instead of a jstring. You can create the jcharArray like this:
int len = strlen(id);
jcharArray charArray = (*env)->NewCharArray(env, len);
(*env)->SetCharArrayRegion(env, charArray, 0, len, id);
Alternatively, you can change your Java code to accept a String instead of a char[]:
public ResultCollector(int err, String id) {
this.err = err;
this.resID = id;
}

Binary Tree in C++/CLI with value is System::String

I have a problem when i try to insert node to binary tree. I don't understand why the argument is always null. Here is my program.
file "BinaryTree.h"
#pragma once
#ifndef BINARYTREE_H
#define BINARYTREE_H
using namespace System;
ref class BinaryTree
{
public:
BinaryTree()
{
root = nullptr;
};
~BinaryTree()
{
destroySubtree(root);
};
void insertNode(String^);
bool searchNode(String^);
void remove(String^);
String^ disPlay()
{
return disPlay(root);
};
private:
ref struct TreeNode
{
String^ values;
TreeNode ^left;
TreeNode ^right;
};
TreeNode ^root;
void insert(TreeNode ^, TreeNode ^);
void deleteNode(String^, TreeNode ^);
void destroySubtree(TreeNode ^);
void makeDeletion(TreeNode ^);
String^ disPlay(TreeNode ^);
};
#endif
And here is file "BinaryTree.cpp"
#include "BinaryTree.h"
using namespace System;
void BinaryTree::insert(TreeNode ^node, TreeNode ^newNode)
{
if (node == nullptr)
node = newNode;
else if (newNode->values->CompareTo(node->values)<0)
insert(node->left, newNode);
else
insert(node->right, newNode);
}
void BinaryTree::insertNode(String^ s)
{
TreeNode ^newNode = gcnew TreeNode;
newNode->values->Copy(s);
newNode->left = newNode->right = nullptr;
insert(root, newNode);
}
bool BinaryTree::searchNode(String^ s)
{
TreeNode ^node = root;
while (node)
{
if (node->values->CompareTo(s)==0)
return true;
else if (node->values->CompareTo(s) > 0)
node = node->left;
else
node = node->right;
}
return false;
}
void BinaryTree::remove(String^ s)
{
deleteNode(s, root);
}
void BinaryTree::deleteNode(String^ s,TreeNode ^node)
{
if (node->values->CompareTo(s) > 0)
deleteNode(s, node->left);
else if (node->values->CompareTo(s) < 0)
deleteNode(s, node->right);
else
makeDeletion(node);
}
void BinaryTree::makeDeletion(TreeNode ^node)
{
TreeNode ^tempNode;
if (node == nullptr){}
else if (node->right == nullptr)
{
tempNode = node;
node = node->left;
delete tempNode;
}
else if (node->left == nullptr)
{
tempNode = node;
node = node->right;
delete tempNode;
}
else
{
tempNode = node->right;
while (node->left)
{
tempNode = tempNode->left;
}
tempNode->left = node->left;
tempNode = node;
node = node->right;
delete tempNode;
}
}
void BinaryTree::destroySubtree(TreeNode ^node)
{
if (node)
{
if (node->left)
{
destroySubtree(node->left);
}
if (node->right)
{
destroySubtree(node->right);
}
delete node;
}
}
String^ BinaryTree::disPlay(TreeNode ^node)
{
String^ s;
if (node)
{
s = node->values;
return s+=disPlay(node->left);
return s+=disPlay(node->right);
}
return s;
}
When I use like this:
BinaryTree^ Tree = gcnew BinaryTree();
string key="abc0123456";
String^ sss = gcnew String(key.c_str());
Tree->insertNode(sss);
MessageBox::Show(Tree->disPlay());
but the result always null,when i check at step "Tree->insertNode(sss);" then the argument "sss" in function "insertNode(String^ s)", it mean variable "s" is null.
What should i do now to fix this problem?
Anyone can help me pls
Because String.Copy is static method, I believe. It returns back string which is not assigned to value field anywhere in you code
Something like
newNode->values = String::Copy(s);
might work
Your disPlay method will not recurse to right branches ever, Because it returns values + left recursion only.
I believe your intentios was something more like this:
String BinaryTree::disPlay(TreeNode ^node)
{
String s;
if (node)
{
s = node->values;
s+=disPlay(node->left);
s+=disPlay(node->right);
}
return s;
}

Trying to handle thread pool in a class

I'm trying to handle thread pool in a class.
below is my code.
#include <Windows.h>
class ClassA
{
public : // user API
ClassA()
{
}
~ClassA()
{
}
public : //my muiti-thread func
void init()
{
//*************************************
// multithread Initialization
//*************************************
pool = NULL;
cleanupgroup = NULL;
rollback = 0;
bool bRet = false;
pool = CreateThreadpool(NULL);
if(NULL == pool)
{
goto cleanPool;
}
rollback = 1;
SetThreadpoolThreadMaximum(pool, 5);
bRet = SetThreadpoolThreadMinimum(pool, 10);
if (FALSE == bRet) {
goto cleanPool;
}
cleanupgroup = CreateThreadpoolCleanupGroup();
if (NULL == cleanupgroup) {
goto cleanPool;
}
rollback = 2;
SetThreadpoolCallbackPool(&CallBackEnviron, pool);
SetThreadpoolCallbackCleanupGroup(&CallBackEnviron,
cleanupgroup,
NULL);
return ;
cleanPool:
switch (rollback)
{
case 2:
// Clean up the cleanup group.
CloseThreadpoolCleanupGroup(cleanupgroup);
case 1:
// Clean up the pool.
CloseThreadpool(pool);
default:
break;
}
return ;
}
void foo()
{
PTP_WORK work = NULL;
work = CreateThreadpoolWork(ClassA::_delegate,
NULL,
&CallBackEnviron);
}
static void __stdcall _delegate(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WORK Work)
{
//some code
}
PTP_POOL pool;
UINT rollback;
TP_CALLBACK_ENVIRON CallBackEnviron;
PTP_CLEANUP_GROUP cleanupgroup;
};
int main()
{
ClassA a;
a.init();
a.foo();
}
If you make a project and execute this code, it gets unhandled execption...
I have no clue why...
I think the exception is caused by an uninitialized structure CallBackEnviron. The documentation states that this structure must be initialized by InitializeThreadpoolEnvironment

WCF - A newbie question about Tasks an WCF ;

this is the best approach for WCF inside tasks ?;
var tsk1 = Task.Factory.StartNew<list<object>>(()=> {
Mysvc svc1 = new Mysvc();
var t = svc1.getData();
scv1.Close();
return t;
});
var tsk2 = Task.Factory.StartNew<list<object>>(()=> {
Mysvc svc1 = new Mysvc();
var t2 = svc1.getData();
scv1.Close();
return t2;
});
Task.WaitALL(tsk1,tsk2);
var res = tsk1.Result;
var res2 = tsk2.Result;
Thnak you very much
If you have an asynchronous version of the contract (which, if you're using svcutil or add service reference, you can get by specifying the proper option), you can use the Task.Factory.FromAsync method to do that as well:
public class StackOverflow_6237996
{
[ServiceContract(Name = "ITest")]
public interface ITest
{
[OperationContract]
int Add(int x, int y);
}
[ServiceContract(Name = "ITest")]
public interface ITestAsync
{
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object userState);
int EndAdd(IAsyncResult asyncResult);
}
public class Service : ITest
{
public int Add(int x, int y)
{
Thread.Sleep(100);
return x + y;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
host.Open();
Console.WriteLine("Host opened");
ChannelFactory<ITestAsync> factory = new ChannelFactory<ITestAsync>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
ITestAsync proxy = factory.CreateChannel();
var tsk1 = Task.Factory.FromAsync<int>(
proxy.BeginAdd(4, 5, null, null),
(ar) => proxy.EndAdd(ar));
var tsk2 = Task.Factory.FromAsync<int>(
proxy.BeginAdd(7, 8, null, null),
(ar) => proxy.EndAdd(ar));
Task.WaitAll(tsk1, tsk2);
Console.WriteLine("Result 1: {0}", tsk1.Result);
Console.WriteLine("Result 2: {0}", tsk2.Result);
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}

Resources