Swig+Java: namespaces and packages - java

Assume the C++ class structure like this:
namespace MainNS
{
namespace A
{
class Class
{
//...
};
}
namespace B
{
class Class
{
//...
};
}
//...
}
I have followed this SWIG docs: http://www.swig.org/Doc3.0/Java.html#Java_namespaces
In interface files I define the following to create packages on Java side:
%nspace MainNS::A::Class
%nspace MainNS::B::Class
and then have to use java pragma to place the JNI file into "appropriate" place (somewhere where classes can access it - that's the core of the problem, please see below):
%pragma(java) jniclasspackage = "MainNS::A" //or "MainNS::B"
Now, everyone from class MainNS::A::Class (package MainNS.A) can access generated <modulename>JNI class.
However, namespace B ended up in different package MainNS::B and MainNS::B::Class (package MainNS.B) can't access <modulename>JNI class.
What is the solution for this problem? As far as I understand there is no SWIG option to split the generated JNI class with native function signatures?

This is quite an old thread, but since I came across a similar issue:
the way I would solve this is to create two different modules, A and B (and so two different swig interface files A.i and B.i). you can import each file (use %import not %include)
%module A
%{
#include <MainNS/A.hxx>
%}
%feature(nspace);
%pragma(java) jniclasspackage="MainNS.A";
%import "B.i"
%include <MainNS/A.hxx>
Then B.i:
%module B
%{
#include <MainNS/B.hxx>
%}
%feature(nspace);
%pragma(java) jniclasspackage="MainNS.B";
%import "A.i"
%include <MainNS/B.hxx>
Links:
Working with modules: http://www.swig.org/Doc3.0/SWIGDocumentation.html#Modules
Namespace support: http://www.swig.org/Doc3.0/SWIGDocumentation.html#SWIGPlus_namespaces

Related

JNI: dealing with a complicated C++ class

I have a 3rd party Win32 dll, written in C++, which I need to load in my eclipse java project and call some methods from it. What is problematic - all the classes which I really need from this dll have virtual functions. I've created a dummy C++ project, which received all the stuff via static linking and via my self-defined C++ class. Everything is working in my C++ world. Now I want to load my dummy dll (which in turn loads all other stuff I need) in my java project. The code in cpp world looks like this (I've mixed up .h and .cpp for simplicity):
class Dummy : public VirtualClassFromLib
{
public:
//...
//some standard stuff here
//...
void method1()
{
VirtualClassFromLib::function1();
}
void method2()
{
//a header is loaded with #include
AdditionalStructureFromHeader object;
VirtualClassFromLib::function2(object);
}
void virtual_function()
{
std::cout << "Cool, now you are not virtual";
}
//...
}
where function1 and function2 are not virtual in the base class and virtual_function is.
I'm a newbie in JNI and as far as I understood, I should write a "mirror" class with the same method's and other stuff's names in my java project. Question: how to deal with this VirtualClassFromLib? Like, this VirtualClassFromLib has a very complicated structure with a wide usage of self-defined structures in the original dll. Or don't I need to "mirror" that completely to java project? I don't get it from examples and tutorials in the Internet.

SWIG: using imported external type

I am trying to wrap some libraries written in C++ to interface with JAVA using SWIG.
I have one C++ struct in one library used in one C++ function of another library as an argument.
common.h
namespace rina {
namespace cdap_rib {
typedef struct{
int size_;
void* message_;
} ser_obj_t;
}
}
This library is wrapped producing a class called eu.irati.librina.ser_obj_t in JAVA. That's fine. Then I have
utilities.h
class IPCPConfigEncoder {
public:
void encode (rina::cdap_rib::ser_obj_t& ser_obj);
}
which is wraped with SWIG producing
public void encode(SWIGTYPE_p_rina__cdap_rib__ser_obj_t ser_obj) {
...
}
in a JAVA class. Looking around in I found (SWIG Importing generated class from a different module and package into the current class) and I added to .i
%typemap(javaimports) SWIGTYPE
%{
import eu.irati.librina.ser_obj_t;
%}
which produced
import eu.irati.librina.ser_obj_t;
public void encode(SWIGTYPE_p_rina__cdap_rib__ser_obj_t ser_obj) {
...
}
Then, I have a couple of questions
The import is added to all the java classes... how can I enclose it only to the desired class?
How can I tell SWIG to change SWIGTYPE_p_rina__cdap_rib__ser_obj_t for eu.irati.librina.ser_obj_t.
Note: Since common.h and utilities.h are in different libraries I can not put them together in the same swig module.
As #Felxo pointed in the coments, the only solution is to tell swig to understand also the other libraries interface wraping (so headers and how are they wrapped).
What I did:
I copied common.i into utilities wrapping folder.
I added into utilities.i
/* this is the "copied" common.i */
%import "common.i"
%pragma(java) jniclassimports=%{
import eu.irati.librina.ser_obj_t;
%}
to add the import of the proxy class (you should change thais to point to your proxy class from a java path)
Remove from the copied common.i the unecessary instructions like %template, remember that, at this point, you are only "importing" the common.h, not wrapping it (you already wraped it before). Actually, the common.i should only include:
%{
#include "common.h"
}%
but no
%include "common.h"
Tell SWIG where are is the common.h as well as where is the utilities.husing the -I option

Java + JNA : The specified procedure could not be found

I'm trying to create a dll file using visual studio and use/access it in a java project. The library seems to get loaded, but always the same exception is thrown:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'function': The specified procedure could not be found.
My C/C++ skills ar not the best so the problem could be there. I tried to edit h and cpp files, using classes, namespaces, static methods and other staff found on the web, but nothing to do.
I have also seen other post talking about Depency Walker Tool, but it isn't able to open my dll, i also saw that the compiler add some strange suffixes to the function name, as i understood it's possible to avoid it by using "estern 'C'" in the h or cpp file, but i wasn't able.
My interface:
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface SimpleDll extends Library {
SimpleDll instance = (SimpleDll) Native.loadLibrary("SimpleDll", SimpleDll.class);
void function();
}
My Main class:
public class Test_Dll {
public static void main(String[] args) {
SimpleDll simpleDll = SimpleDll.instance;
simpleDll.function();
}
}
My h file:
#ifndef SIMPLEDLL
#define SIMPLEDLL
namespace simpeDll{
static void function();
}
#endif
My cpp file:
#include "stdafx.h"
#include "simpleDll.h"
#include <stdexcept>
using namespace simpeDll;
static void function(){
}
Make sure declaring your function outside the simpleDll namespace.
Make sure to decorate it w/ extern "C"
Make sure exposing your function __declspec(dllexport) void __cdecl function(); or use module definition file

"UnsatisfiedLinkError" on Android JNI

In my project, I have a wrapper class named PlayerCluster.java, which loads the native lib, and provides native functions. If I changed the class name (PlayerCluster.java) or its package, I get java.lang.UnsatisfiedLinkError when native function is invoked.
Why do I get this error when I rename the class name? Is there an approach by which native lib must be loaded in a specific java class?
If you rename the class then you must also rename your JNIEXPORT methods in your native library so they match the new Java class name and then rebuild your native lib.
For example, given this method signture:
JNIEXPORT jobjectArray JNICALL
Java_com_mn_rootscape_utils_NativeMethods_getFilesPermissions( JNIEnv* env, jobject thizz, jobjectArray filePathsArray )
NativeMethods is the Java class which, as you can see, is part of the native function signature.

SWIG C++ structure to java

I'm trying to get a simple SWIG example to work that uses a struct as a return type, but my generated file is incorrect. My files look like this.
SwigTest.h
#pragma once
#include "MyHeader.h"
class SwigTest
{
public:
MyHeader testMe();
};
MyHeader.h
struct MyHeader {
int x;
}
and my swig interface file is:
%module MyModule
%{
#include "SwigTest.h"
#include "MyHeader.h"
%}
extern MyHeader testMe();
The resulting JNI file has the following method declaration
public class MyModuleJNI {
public final static native long testMe();
}
If my method returns a primitive, it works fine, but not with the struct. I'm running on windows with swig.exe -java -c++ MyModule.i
EDIT: I think I need to declare a struct in the .i file as well. Could someone confirm (or dispute) that? Thanks.
thanks,
Jeff
Yes you need to declare the struct in the interface file as well.
Try this:
%module MyModule
%{
#include "MyHeader.h"
#include "SwigTest.h"
%}
%include "MyHeader.h"
%include "SwigTest.h"
Also its safer to declare the struct before the code that makes use of it.

Categories

Resources