Can someone explain the difference between the one-argument form and the two-argument form of Init when creating a c++ node.js addon?
void Init(Local<Object> exports) {}
void Init(Local<Object> exports, Local<Object> module) {}
In general you could always use the second method template, but exports or module provide different options.
Using the following example:
void Init(Local<Object> exports) {
NODE_SET_METHOD(exports, "test", MyTest);
}
will add the function test as a "function property" on your exports object.
So you could use the following JS code and it would, for example, print it out to the stdout using the test function from your exports object:
const test = require('./path/to/node/addon/addon.node');
test.test('my message');
On the other hand:
void Init(Local<Object> exports, Local<Object> module) {
NODE_SET_METHOD(module, "exports", MyDummyCallback);
}
Provides you with the full module (module) and allows you to override your exports. You could call something like this from JS:
const test = require('./path/to/node/addon/addon.node');
test('test');
Will print your test message to the tty using the overridden module.
Related
I have a problem in which a function call during executing is calling a completely wrong implemented interface function that is overloaded. I call a function passing a bool parameter and the implemeted function actually being called is the one with a float paramater...
Here's my use case, may be a little bit confusing:
I'm writing a game in which a user will write arduino code in a Unreal Engine (UE) widget that will be saved into a .cpp file.
Behind the curtains, usercode.cpp (saved file) will get the user written code and "inject" some useful stuff, making a small code look like this:
#include "IArduino.h"
extern "C"
{
__declspec(dllexport) void setup();
__declspec(dllexport) void loop();
__declspec(dllexport) void InitArduinoPtrs(IArduino*);
};
IArduino* arduinoPtr = nullptr;
void InitArduinoPtrs(IArduino* InArduinoPtr)
{
arduinoPtr = InArduinoPtr;
}
void setup()
{
arduinoPtr->pinMode(true);
}
**Injected code: "IArduino.h", "extern C stuff", "arduinoPtr" and "InitArduinoPtrs()"
I have a interface called "IArduino" that has a function defined as virtual that is overloaded (test only):
class IArduino
{
public:
virtual void pinMode(float) = 0;
virtual void pinMode(bool) = 0;
};
I'm compiling this usercode.cpp as a shared library (usercode.cpp using IArduino.h):
g++ -c -I[IArduino.h_PATH] -Wall -fpic ./usercode.cpp -o ./usercode.o 2>&1
g++ -shared -o ./usercode.so ./usercode.o 2>&1
On my Unreal Engine project, I created a "ArduinoImpl[.h,.cpp]" that implements "IArduino" interface:
class ARDUCOMPILATIONTEST_API ArduinoImpl : public IArduino
{
public:
void pinMode(bool portNumBoolTest);
void pinMode(float portNumTest);
};
At runtime in Unreal Engine, I'm using GetProcAddress() to get setup() and InitArduinoPtrs() functions.
With linked InitArduinoPtrs(), I call it passing the pointer to a new object of "ArduinoImpl()" (that implements IArduino.h):
At another class that runs in runtime:
m_setup_function = (m_setup)FPlatformProcess::GetDllExport(m_dllHandle, TEXT("setup"));
m_init_function = (m_init)FPlatformProcess::GetDllExport(m_dllHandle, TEXT("InitArduinoPtrs"));
ArduinoImpl* arduinoImplPtr = new ArduinoImpl();
if (m_init_function)
m_init_function(arduinoImplPtr);
if (m_setup_function)
m_setup_function();
My problem is, usercode.cpp setup() is run, then:
When the "arduinoPtr->pinMode(true)" is called, it's calling "ArduinoImpl::pinMode(float)" instead of "ArduinoImpl::pinMode(bool)", completely messing up the overloaded call. Moreover, if I try to write "arduinoPtr->pinMode(2.5f)", it calls the bool overload instead of float overload... The same thing happens if I try with different parameters, such as int, string, etc.
Does anybody know why this is happening?
I tried logging the results, such as logging the float I receive when "arduinoPtr->pinMode(true)" is called and I get garbage value (such as 0.5, 512.803, 524288.187500, ...). Trying to log the "bool" value when "arduinoPtr->pinMode(2.5f)" is called, I get "208".
I tried forcing a cast on call like "arduinoPtr->pinMode(static_cast(true))" and it still calls the float param overloaded function.
I tried with different params type and the same thing keeps hapenning.
I am working on updating an embedded Python2.7.14 interpreter to an Python3.9.7.
Here is my problem, the interpreter is used for scripting in a c++ programm. For scripting there is an internal libary called _internal. It's defined by using Boost 1.7.0:
BOOST_PYTHON_MODULE(_internal)
{
python::def("foo", foo);
}
With the py2 it worked to import the libary like this
void init_ConvertCString();
extern "C" void init_internal();
/.../
static CString strPath(Common::Path::GetShortPath(Common::GetApplicationPath()));
Py_SetProgramName(strPath.GetBuffer());
strHome(Common::Path::GetShortPath(Common::Path::Normalize(Common::GetApplicationPath()+"..\\Runtime\\Scripting\\")));
Py_SetPythonHome(strHome.GetBuffer());
Py_Initialize();
init_ConvertCString();
init_internal();
PyObject* module = ::PyImport_Import(PyString_FromString(_T("sys")));
PyObject* _internal = ::PyImport_Import(PyString_FromString(_T("_internal")));
if (module)
PyObject_SetAttrString(module, _T("stdin"), _internal);
But sadly for reasons i am not able to work, out it's not working on py3 anymore. I replaced all the py2 functions for py3 ones:
void init_ConvertCString();
extern "C" void PyInit__internal();
/.../
static CString strPath(Common::Path::GetShortPath(Common::GetApplicationPath()));
static CString strHome(Common::Path::GetShortPath(Common::Path::Normalize(Common::GetApplicationPath()+"..\\Runtime\\Scripting\\")));
Py_SetPythonHome(CA2W(strHome.GetBuffer(), CP_UTF8));
Py_Initialize();
init_ConvertCString();
PyInit__internal();
PyObject* module = ::PyImport_Import(PyUnicode_FromString(_T("sys")));
PyObject* _internal = ::PyImport_Import(PyUnicode_FromString(_T("_internal")));
if (module)
PyObject_SetAttrString(module, _T("stdin"), _internal);
The function
::PyImport_Import(PyUnicode_FromString(_T("_internal")));
is returning null. All the paths stayed the same.
Is there somthing i missed? After a few hours of debugging i start to lose my sanity.
I found the solution to make it run again:
change the datatype from void to an PyObj
extern "C" PyObject * PyInit__internal();
added befor the Py_Initialize(); the line
PyImport_AppendInittab("_internal", &PyInit__internal);
now the module can be loaded.
This question already has answers here:
Calling C++ dll from Java
(3 answers)
Closed 8 years ago.
I have one c++ dll which is previously used for c# application. now we want to use the same dll for java . i know that we can use JNI technology for this but the problem we have to use the same method signature we don't want to change the method singnature. please advise me.
One option is using JNA instead of JNI. It eliminates the need for the boilerplate native code. An example would look something like this...
import com.sun.jna.Library;
import com.sun.jna.Native;
public class Example {
public interface NativeMath extends Library {
public bool isPrime(int x);
}
public static void main(String[] args) {
int x = 83;
NativeMath nm = (NativeMath) Native.loadLibrary("nm", NativeMath.class);
System.out.println(x + " is prime: " + nm.isPrime(x));
}
}
You don't have to change the method signature, you simply add a native method which then calls the native C++ code. Here is a simple example:
public class Someclass
{
public native void thisCallsCMethod(Someparams);
}
Now create the JNI wrappers:
javac Someclass.java
javah Someclass
This will create a Someclass.h, then you create Someclass.cpp and include the .h in it.
At this point all you have to do is write the C/C++ code for thiCallsCMethod
In the .h you'll see a method signature that you have to implement. Something along the lines of:
#include "clibraryHeader.h"
using namespace clibraryNamespace;
JNIEXPORT void JNICALL thisCallsCMethod(JNIEnv *, someparameters)
{
cout<<"Yeah C code is being called"<<endl;
someCfunction();
}
Obviously you have to massage the parameters in the JNI call, but you can create some temporary variables, then copy back the values you get from the C calls into the incoming parameters (if they need to be returned) etc.
Maybe:
#include "clibraryHeader.h"
using namespace clibraryNamespace;
JNIEXPORT void JNICALL thisCallsCMethod(JNIEnv *, someparameters)
{
cout<<"Yeah C code is being called"<<endl;
Cstruct temp;
temp1.somevar = param1.getSomeVal()
someCfunction(temp);
}
I'm kinda' new to JNI, but been reading alot about JNI when I wanted to use a legacy dll in my project.
Quick enough, I found out that I can't parameters to native methods. Here's an example that I tried to code with no success:
Hello.java:
package HelloWorld;
Public class Hello {
Private static native int HelloWorld();
Private static native int Mirror(int a);
Static {
System.loadLibrary("Example"); //got path in
vm arguments - works.
}
Public static void main(String[] args) {
Int a = 8;
System.out.println(Mirror(a));
}
Used javah to create header which got me this signature:
JNIEXPORT jint JNICALL Java_HelloWorld_Hello_Mirror (JNIEnv *, jclass, jint);
Wrote a cpp:
Same signature as the h with impl of: "return 1";
That's it and... This is the error I get from eclipse:
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld/Hello.Mirror(I)I
at HelloWorld.Hello.main (Hello.java:14)
These are my ideas:
A. Saw something about c and cpp, am I mixing things.
B. jdk or stuff?
C. The library loads perfectly (checked the other function that does not get parameters), maybe the types are incompatible?
Stuck on this for a while, Hope you guys can help me!
Solved!
Just needed to add '{' around both functions in the cpp file, after the "extern c" command...
I have a main project and a DLL project. The main executable links to the DLL.
In the main project I have a function:
int func(char *str)
{
.....
}
In the DLL project, I want to use this function. Can I forward declare this function and use it? Like:
int func(char *str);
int dllFunc()
{
...
status = func(str);
...
}
One (fairly common) way of doing it is to provide a callback from the application, i.e.
In DLL:
typedef void (*callback)();
callback my_callback;
void dll_register_callback(callback app_callback) { my_callback = app_callback; }
void do_things() { my_callback(); }
In application:
void cb() {}
dll_register_callback(cb);
You cannot use forward declaration forward declaration is something different. If you want call some method in dll, you have to use GetProcAdress or Implicit linking.
Anyway, It look that you want to call method placed inside you executable from some DLL, it can be done as far as I know. And it doesn't make much sense, because DLL is designed to be shared between application not main executable.