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
Related
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.
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
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
By running System.loadLibrary("myAPI"), I verified that the DLL file "myAPI.dll" can be successfully loaded into my Eclipse Java project. Now I need to call methods specified inside this DLL file from my Java code. To do this, I added JNA to my Java project. Then I wrote the below-given code snippet that should be able to get instances of classes IProject and ProjectFactory (specified in the DLL file).
I still don't understand how to properly implement this with JNA. I checked different threads, e.g. this one, but the ones I checked don't provide an answer. Any help is highly appreciated. Thanks.
import com.sun.jna.Library;
import com.sun.jna.Native;
public class MyClass {
public interface myAPI extends Library {
//...
}
void LoadProj() {
myAPI api = (myAPI) Native.loadLibrary("myAPI",myAPI.class);
String fileName = "xxx.sp";
IProject project; // this is wrong but shows what I am trying to do
try {
project = ProjectFactory.LoadProject(fileName);
}
catch (Exception ex) {
MessageBox.Show(this, ex.Message, "Load failure");
}
}
}
Not sure what problem you are facing but as a practice your myAPI interface should declare all the methods verbatim with appropriate parameter mapping. I don't see any methods inside your interface.
Please checkout the this link as well as the link mentioned above by #Perception
If there are no Java classes or Java source hidden inside this DLL (which would be ... strange), then it will never work this way. You can't instantiate C# classes or use C# interfaces. MessageBox.Show( isn't Java either, it is Windows Forms code.
How can I convert the code below from Jython to Java?
The code will be used to run the Junit test to set the proxy details to make JUnits more usable.
Jyhon code:
from java.lang import *;
from com.parasoft.preferences import *;
from com.parasoft.proxy import *;
def SetupProxy(item, context):
preferences = AppPreferenceProvider.getProxyPreferenceProvider();
preferences.setProxyConfiguration("bisn.parasoft.com", "3128", "", "", "", "")
preferences.setUseProxy(1)
preferences.setUseProxyAutoConfig(0);
preferences.setUseSameProxySettings(1)
preferences.setUseProxyAuthentication(1)
preferences.setProxyUserId("devtest")
preferences.setProxyPasswd("dev%pass")
preferences.setSystemProxy(Boolean(0));
Since jython compiles into a .jar, there is no reason to convert the source code into java. However, if you really need to this, it is almost straightforward:
Add the package .... line to the top
Change all from a import b into import a.b (in your case, b is *, though you should avoid that)
The function must be inside a class and probably static. You could for example call the class SetupProxy, too.
The variables (item, context and preferences) must have a type declaration.
Of course, you can also decompile the .jar generated via jython to get some inspiration...