JNI: Calling a Java method in C++ with an object as argument - java-native-interface

I'm new to JNI and have a Java program given, from which I want to call methods in C++.
I have an ObjectA implemented in Java. I receive its classID like this in C++:
jclass cls = env->FindClass("myPackages/ObjectA");
Now I have the method funcA given in Java. funcA accepts an Object of the type ObjectA as an argument and returns an integer. The declaration in Java looks like this:
public int funcA( ObjectA obj);
Now I want to get the methodID of funcA in C++. The problem is, I don't know how to specify which parametertype the method gets. I know that I have to write L fully-qualified-class ; to pass Objects like a String, but how do I do this, when the objects are not from official javalibraries but objects I created?
I tried this, but it obviously didn't work:
jmethodID jfuncA = env->GetMethodID(cls, "funcA", "(Lcls;)I");
All I got as a response is, that the Method was not found. So what do I have to write instead of (Lcls;)? Or is this impossible?
Any idea is useful!

Run javap -s on your compiled Java class and use exactly what it tells you as the signature of the native method. Cut and paste. Don't waste your time trying to figure it out for yourself when you have a tool that is never wrong.

Related

How to create a C++ compatible function object in LUA?

I'm thinking about how to design my APIs, I plan to have a C++ application with a scripting layer in LUA .
For a couple of key points in my design I would like to give the ability to the user to create a function object that represents what he wants to do in LUA, than send this function object from LUA to C/C++ .
In pseudo code, in C++ I have a class T
class T {
...
int num1 = 0;
float num2 = 0.0f;
std::string str{"NONE"};
...
};
And I would like to manipulate an instance of T with a function object provided from LUA like so
void applyFunc(T t,F f){
f(t);
}
The problem is that I can't find nothing in LUA that creates a function object like a C++11 lambda or std::function or any other object that can be considered a function object.
Really my point is: how to define a C++ compatible function object in LUA ?
The problem is that I can't find nothing in LUA that creates a function object like a C++11 lambda or std::function or any other object that can be considered a function object.
That's what the function keyword does.
This is a lambda. It's easy enough to pass these to C++ and let the C++ code call them.
As for this:
void applyFunc(T t,F f){
f(t);
}
In principle it's easy: push the C++ object pointer onto the Lua stack as a userdata and call the Lua function. The problem is the Lua code can't do anything with a C++ pointer.
If you want the Lua code to be able to manipulate the object you pass it, you'll need to write manipulator methods in C++ and expose them to Lua. You usually do that by creating a metatable for the userdata.
There are libraries that this that automatically for C++. If you want to do it by hand (my preference), you should probably start here.
If you Google "C++ object Lua __index" that should net you numerous examples. I could code up an example later, but I'm at work at the moment.

Getting the address of an Objective-C method

I am new to Objective-C and I need to overcome the following issue.
I am trying to develop a front-end for a C library and I need to somehow get the address of an Objective-C member function and pass it to the library.
For instance: here's what I would do in C++
class MyClass
{
public:
void my function();
void some_other_function()
{ connect_signal(my_function); }
};
Here, I just pass the address of my_function() to connect_signal.
Is that possible in Objective-C? Any other ideas?
My second choice would be to simply write a C function out of the class that would call the Objective-C function.
Thanks in advance
There’s a methodForSelector: method that returns an IMP, a pointer to the implementation of a method for given selector (related question). Is that what you’re after?
And as a more general remark, using a pointer to a method implementation is usually too much magic. Is there a higher-level, more “ordinary” solution to your use case? (I can’t really imagine the details from what you wrote in the question.)
For the record, you can't connect a signal to a nonstatic C++ function. At least not in the *nix meaning of signals. Those need a this pointer for invokation.
Now, about Objective C. Depends on what do you want to do - pass a pointer to an Objective C method to a plain-C API, or implement a signal-like callback mechanism of your own. Other answers concentrate on the former; let's talk the latter.
The natural thing to do is passing around a combination of a selector and an object pointer. Selectors have datatype SEL and are retrieved using the #selector() construct. A selector is a piece of data (really an integer) that uniquely identifies a method within a class hierarchy.
Let's imagine you have a connect_signal function somewhere that wants a callback:
-(void)connect_signal:(SEL)callbackSelector forObject:(NSObject*)callbackObject;
You call it like this (from within the callback object):
[xx connect_signal:#selector(MyMethod:) forObject:self];
Within the function, you save the selector and the object pointer. When you need to invoke the callback, you would issue the following call:
[SavedCallbackObject performSelector:(SavedCallbackSelector) withObject: nil];
The second parameter is for passing parameters to the callback; if you need more than one, see NSInvoke.
My answer is assuming Cocoa. NSObject, e. g. is a Cocoa class. It's a safe bet for ObjC questions these days, considering.
Or you can use good old function pointers. They're still around.
An Objective-C method implementation (IMP) is a C function that takes at least two arguments; the target of the method call (self) and the selector to be invoked (_cmd).
Thus, passing an IMP to your C API won't work.
Your best bet is to pass a C function. Assuming your C API is sensible and has an "arbitrary user context pointer thingy", something like:
void myfunc(void *context) {
[(MyClass *)context callback];
}

How can we properly implement Python bindings of subclassed C++ objects?

I'm having an issue with a rather intricate interaction of C++ and Python that I'm hoping the community can help me with. If my explanation doesn't make sense, let me know in the comments and I'll try to clarify.
Our C++ code base contains a parent classes called "IODevice" which is a parent to other classes such as "File" and "Socket" and so forth. We've done this so that in much of our code we can work generically with "IODevice" objects that might actually be files or sockets or whatever we originally constructed. This all works fine within the C++ code.
We've started to build Python bindings for some of our objects. We didn't want to modify the original "File" or "Socket" classes; we created "FilePy" and "SocketPy" subclasses of the "File" and "Socket" classes. These *Py classes contain the necessary Python binding code.
Here's where the problem starts. Let's say I have a "InputProcessorPy" C++ class that has the appropriate Python bindings. I would want to be able to construct it in my Python code and pass it a "FilePy" or "SocketPy" object that the "InputProcessorPy" is going to pull data from. The Python binding code from "InputProcessorPy" looks like this:
PyObject* InputProcessor::PyMake(PyObject* ignored, PyObject *args)
{
PyObject* cD_py;
IODevice* inputFile;
if (!PyArg_ParseTuple(args, "O", &cD_py))
return NULL;
inputFile = (IODevice*) cD_py;
inputFile->isReadable();
printf("------>>>> Done\n");
return (PyObject *) new CL_InputRenderer(*inputFile, InputProcessor::Type);
}
If I run this code, I get a segmentation error when I call the isReadable() method of inputFile, which is actually a method of the IODevice base class.
If instead I do this:
...
FilePy* inputFile;
...
inputFile = (FilePy*) cD_py;
inputFile->isReadable();
...
The code works fine in this case. This, however, is undesirable, as it assumes we are passing in a "FilePy" object, which will not be the case; it might be a "SocketPy" or "BufferPy" or "StringPy" or any other sort of "IODevice" subclass.
It seems as if the Python binding process is somehow not compatible with the C++ class inheritance structure that we're trying to use. Has anyone tried to solve an issue like this before? Are we doing our C++ inheritance wrong, or should we be doing something different in our Python bindings to make this work?
Are your types FilePy and IODevice derived from PyObject? Otherwise, the C++ compiler will interpret:
inputFile = (IODevice*) cD_py;
as:
inputFile = reinterpret_cast<IODevice*> (cD_py);
rather than what you expected:
inputFile = dynamic_cast<IODevice*> (cD_py);
If the actual type passed is not PyObject, or IODevice is not related to PyObject via inheritance, there is no way for the C++ compiler or runtime to know how to find the proper vtable.

python object to native c++ pointer

Im toying around with the idea to use python as an embedded scripting language for a project im working on and have got most things working. However i cant seem to be able to convert a python extended object back into a native c++ pointer.
So this is my class:
class CGEGameModeBase
{
public:
virtual void FunctionCall()=0;
virtual const char* StringReturn()=0;
};
class CGEPYGameMode : public CGEGameModeBase, public boost::python::wrapper<CGEPYGameMode>
{
public:
virtual void FunctionCall()
{
if (override f = this->get_override("FunctionCall"))
f();
}
virtual const char* StringReturn()
{
if (override f = this->get_override("StringReturn"))
return f();
return "FAILED TO CALL";
}
};
Boost wrapping:
BOOST_PYTHON_MODULE(GEGameMode)
{
class_<CGEGameModeBase, boost::noncopyable>("CGEGameModeBase", no_init);
class_<CGEPYGameMode, bases<CGEGameModeBase> >("CGEPYGameMode", no_init)
.def("FunctionCall", &CGEPYGameMode::FunctionCall)
.def("StringReturn", &CGEPYGameMode::StringReturn);
}
and the python code:
import GEGameMode
def Ident():
return "Alpha"
def NewGamePlay():
return "NewAlpha"
def NewAlpha():
import GEGameMode
import GEUtil
class Alpha(GEGameMode.CGEPYGameMode):
def __init__(self):
print "Made new Alpha!"
def FunctionCall(self):
GEUtil.Msg("This is function test Alpha!")
def StringReturn(self):
return "This is return test Alpha!"
return Alpha()
Now i can call the first to functions fine by doing this:
const char* ident = extract< const char* >( GetLocalDict()["Ident"]() );
const char* newgameplay = extract< const char* >( GetLocalDict()["NewGamePlay"]() );
printf("Loading Script: %s\n", ident);
CGEPYGameMode* m_pGameMode = extract< CGEPYGameMode* >( GetLocalDict()[newgameplay]() );
However when i try and convert the Alpha class back to its base class (last line above) i get an boost error:
TypeError: No registered converter was able to extract a C++ pointer to type class CGEPYGameMode from this Python object of type Alpha
I have done alot of searching on the net but cant work out how to convert the Alpha object into its base class pointer. I could leave it as an object but rather have it as a pointer so some non python aware code can use it. Any ideas?
Thanks to Stefan from the python c++ mailling list, i was missing
super(Alpha, self).__init__()
from the constructor call meaning it never made the parent class. Thought this would of been automatic :D
Only other issue i had was saving the new class instance as a global var otherwise it got cleaned up as it went out of scope.
So happy now
May not be the answer you are looking for, but take a look at ChaiScript for embedding in your C++ application.
According to their website,
ChaiScript is the first and only
scripting language designed from the
ground up with C++ compatibility in
mind. It is an ECMAScript-inspired,
embedded functional-like language.
ChaiScript has no meta-compiler, no
library dependencies, no build system
requirements and no legacy baggage of
any kind. At can work seamlessly with
any C++ functions you expose to it. It
does not have to be told explicitly
about any type, it is function
centric.
With ChaiScript you can literally
begin scripting your application by
adding three lines of code to your
program and not modifying your build
steps at all.
Well, I am not sure whether it will help you, but I had the same problem with scripts in Lua. We created objects from Lua and wanted some c++ code to handle the objects via pointers. We did the following:
all object stuff was written in c++, including constructors, destructors and factory method;
lua code was calling a factory method to create an object. this factory method 1) gave the object a unique ID number and 2) registered it in the c++ map, that mapped ID numbers to native pointers;
so, whenever lua was going to pass a pointer to c++ code, it gave an object ID instead, and the c++ code looked up the map for finding the actual pointer by ID.

Objective C in C++ – Out of Scope

I have a little problem with the WOsclib. Not particularly with the library, it's more the callback function. The listen to specific osc commands i have to put up some callback method like
void TheOscStartMethod::Method(
const WOscMessage *message,
const WOscTimeTag& when,
const TheNetReturnAddress* networkReturnAddress)
{
std::cout << "Got the start signal";
start.alpha = 1.0;
}
start is IBOutlet UIImageView.
But the compiler says me, that start is out of scope. If I try to access start in obj-c code, it works like it should.
How can i get my Objective C Objects into the c code or at least call a objective-c function.
Thank you
Make the file an objective C++ file with extension .mm Then you can call object C and C++ objects in the same code.
XCode will call the correct compiler from the file extension (ie adding -x objective-c++ to the compile command)
Not that C++ and objective C are different languages and do not understand each others objects so to move data between them you will need to convert the data to a C type e.g. void, char int and pointers to them.
It sounds like start is an instance variable belonging to some Objective-C object and you're trying to access it just by writing its name from a C++ object. If this is the case, it should be pretty obvious why it won't work: The C++ object doesn't know anything about start. The solution is to somehow give the C++ object a reference to the Objective-C object that owns start.
You'll have to make the start object available to your other code.
You can pass it, you can pass the portions you'll be using, you can create an API for the two code bases to use. There are other options as well, all depending on precisely how you wish to use the various objects
The Solution:
I don't know if this is the best way to do it, but it works.
There must be an empty c object, which later will become our objective c object that holds all the stuff we want to access.
static gsSearchForIp* delegate = NULL;
We must define a function to set the objective c object
void setCallbackDelegate(gsSearchForIp* del)
{
delegate = del;
}
And then call it. ( I called it in the initWithFrame method)
setCallbackDelegate(self);
Now i can call a method with [delegate methodName:firstPara] in my c++ method. In this function i have access to all my stuff that I need from the gsSearchForIp class.