How to call existing c++ dll from java [duplicate] - c++

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);
}

Related

I am doing unit testing using gtest and gmock frameworks and I need help in stubbing/mocking a external C functions used inside class functions

So I am trying to write test cases for my production code but the coverage is drastically low due to the usage of some external C library which cannot be executed without target hardware, So I have no choice but to stub the same. Now the problem is how to stub a C function ?
My production code : prod_code.cpp
int TargetTestClass::targetFunc()
{
if(externalCFunc() == True)
{
statement1; statement2; statement3; /// and so on
}
}
My testcode.cpp generally contains tests like this
//Fixture for Target Test class
class TargetTestClassFixture : public testing::Test {
TargetTestClass* targetTestClassPtr;
void SetUp() {
targetTestClassPtr = new TargetTestClass();
}
void TearDown() {
delete targetTestClassPtr;
}
};
TEST_F (unitTest, test_001)
{
targetTestClassPtr->targetFunc(); //Need to do something here so that externalCFunc() returns true on call
}
What you can do is to create a source file like my_c_stubs.c where you rudimentary implement your C function. For example, the implementation can just return true. Then don't link original source file with the external C function but rather use your stub file. You should still use the original C header. In this way you won't be able to stub inline functions though. If it is required, some more sophisticated approach is needed.
I found 2 solutions to my problem so I am going to answer the same here.
Solution 1 : This involved changing the target source code. Basically you need to write a wrapper that calls the external C functions like below
Class TargetTestClass{
protected:
int targetFunc();
virtual int externalCFuncWrapper(); // Wrapper
};
//call the external C function from the wrapper
int TargetTestClass::externalCFunctionWrapper(){
return(externalCFunc());
}
//Definition of targetFuc in original question
//Now write a mock class for Target Test Class as usual and mock the wrapper function to return what you want to
class MockTargetTestClass : public TargetTestClass{
public: MOCK_METHOD0(externalCFunctionWrapper, int());
};
//Now use the Mock class as needed
TEST_F ( TargetUnitTest, TestingExternalCFuctionCall)
{
MockTargetTestClass mockTargetTestClassObj;
using ::testing::Return;
using ::testing::_;
Expect_Call(mockTargetTestClassObj, externalCFunctionWrapper())
.WillOnce(Return(1));
Assert_EQ(mockTargetTestClassObj.targetFunc(), 1);
}
Solution 2 : Thanks to #kreynolds, I have looked into Fake Function Framework and implemented as follows :
Class TargetTestClass{
protected:
int targetFunc();
//No Code change needed in target source code
};
//In testcode.cpp
#include <gmock-global/gmock-global.h>
MOCK_GLOBAL_FUNC0(externalCFunc, int());
TEST( Unittest, test002){
using ::testing::Return;
using ::testing::_;
EXPECT_GLOBAL_CALL(externalCFunc, externalCFunc()).WillOnce(Return(1));
TargetTestClass targetFunc; //This does not contain any wrapper
EXPECT_EQ(targetTestClassObj.targetFunc(), 1);
}
I am using the second solution as this does not require any change in my source code and easier to use.
Once again thank you everyone for giving your time.

Interacting with C++ classes from Swift

I have a significant library of classes written in C++. I'm trying to make use of them through some type of bridge within Swift rather than rewrite them as Swift code. The primary motivation is that the C++ code represents a core library that is used on multiple platforms. Effectively, I'm just creating a Swift based UI to allow the core functionality to work under OS X.
There are other questions asking, "How do I call a C++ function from Swift." This is not my question. To bridge to a C++ function, the following works fine:
Define a bridging header through "C"
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const char *hexdump(char *filename);
const char *imageType(char *filename);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
Swift code can now call functions directly
let type = String.fromCString(imageType(filename))
let dump = String.fromCString(hexdump(filename))
My question is more specific. How can I instantiate and manipulate a C++ Class from within Swift? I can't seem to find anything published on this.
I've worked out a perfectly manageable answer. How clean you'd like this to be is entirely based upon how much work you're willing to do.
First, take your C++ class and create C "wrapper" functions to interface with it. For example, if we have this C++ class:
class MBR {
std::string filename;
public:
MBR (std::string filename);
const char *hexdump();
const char *imageType();
const char *bootCode();
const char *partitions();
private:
bool readFile(unsigned char *buffer, const unsigned int length);
};
We then implement these C++ functions:
#include "MBR.hpp"
using namespace std;
const void * initialize(char *filename)
{
MBR *mbr = new MBR(filename);
return (void *)mbr;
}
const char *hexdump(const void *object)
{
MBR *mbr;
static char retval[2048];
mbr = (MBR *)object;
strcpy(retval, mbr -> hexdump());
return retval;
}
const char *imageType(const void *object)
{
MBR *mbr;
static char retval[256];
mbr = (MBR *)object;
strcpy(retval, mbr -> imageType());
return retval;
}
The bridge header then contains:
#ifndef ImageReader_hpp
#define ImageReader_hpp
#ifdef __cplusplus
extern "C" {
#endif
const void *initialize(char *filename);
const char *hexdump(const void *object);
const char *imageType(const void *object);
#ifdef __cplusplus
}
#endif
#endif /* ImageReader_hpp */
From Swift, we can now instantiate the object and interact with it like so:
let cppObject = UnsafeMutablePointer<Void>(initialize(filename))
let type = String.fromCString(imageType(cppObject))
let dump = String.fromCString(hexdump(cppObject))
self.imageTypeLabel.stringValue = type!
self.dumpDisplay.stringValue = dump!
So, as you can see, the solution (which is actually rather simple) is to create wrappers that will instantiate an object and return a pointer to that object. This can then be passed back into the wrapper functions which can easily treat it as an object conforming to that class and call the member functions.
Making It Cleaner
While this is a fantastic start and proves that it is completely feasible to use existing C++ classes with a trivial bridge, it can be even cleaner.
Cleaning this up would simply mean that we remove the UnsafeMutablePointer<Void> from the middle of our Swift code and encapsulate it into a Swift class. Essentially, we use the same C/C++ wrapper functions but interface them with a Swift class. The Swift class maintains the object reference and essentially just passes all method and attribute reference calls through the bridge to the C++ object!
Having done this, all of the bridging code is completely encapsulated in the Swift class. Even though we are still using a C bridge, we are effectively using C++ objects transparently without having to resort to recoding them in Objective-C or Objective-C++.
Swift has no C++ interop currently. It's a long-term goal, but is very unlikely to happen in the near future.
In addition to your own solution, there is another way to do it. You can call or directly write C++ code in objective-c++.
So you can create an objective-C++ wrapper on top of your C++ code and create a suitable interface.
Then call objective-C++ code from your swift code. To be able to write objective-C++ code you may have to rename file extension from .m to .mm
Do not forget to release memory allocated by your C++ objects when suitable.
You can use Scapix Language Bridge to automatically bridge C++ to Swift (among other languages). Bridge code automatically generated on the fly directly from C++ header files. Here is an example:
C++:
#include <scapix/bridge/object.h>
class contact : public scapix::bridge::object<contact>
{
public:
std::string name();
void send_message(const std::string& msg, std::shared_ptr<contact> from);
void add_tags(const std::vector<std::string>& tags);
void add_friends(std::vector<std::shared_ptr<contact>> friends);
};
Swift:
class ViewController: UIViewController {
func send(friend: Contact) {
let c = Contact()
contact.sendMessage("Hello", friend)
contact.addTags(["a","b","c"])
contact.addFriends([friend])
}
}
As another answer mentioned, using ObjC++ to interact is much easier. Just name your files .mm instead of .m and xcode/clang, gives you access to c++ in that file.
Note that ObjC++ does not support C++ inheritance. I you want to subclass a c++ class in ObjC++, you can't. You will have to write the subclass in C++ and wrap it around an ObjC++ class.
Then use the bridging header you would normally use to call objc from swift.

How to use header file in SystemC Hello World program?

I'm migrating from C++ to SystemC, met following basic questions. (I've searched in google, but only got examples in a single .cpp file). Thanks in advance.
I know following "hello.cpp" works:
//hello.cpp
#include "systemc.h"
SC_MODULE (hello_world) {
SC_CTOR (hello_world) {
}
void say_hello() {
cout << "Hello World.\n";
}
};
int sc_main(int argc, char* argv[]) {
hello_world hello("HELLO");
hello.say_hello();
return(0);
}
Question 1: How can I separate it into hello.h and hello.cpp? Following code is in C++, I don't know how to create the equivalent SystemC code.
//hello.h
class hello_world
{
public:
hello_world();
void say_hello();
};
//hello.cpp
hello_world::hello_world()
{
}
hello_world::say_hello()
{
cout << "Hello World.\n";
}
Question 2: How to create nested class in SystemC? E.g. what is the equivalent SystemC code according to following C++?
class foo
{
public:
int fooAttr1;
class bar
{
public:
int barAttr1;
};
};
Question 3: Where is the best place to specify an attribute/operation's scope? (public/protected/private).
When separating out the implementation from the declarations in SystemC, you can do it the normal way as it is done in C++.
But when you want a constructor with more than one argument(except the default one i.e. SC_CTOR accepts the module name) you will have to define your own constructor.
And if the module has SystemC processes(SC_THREAD, SC_METHOD, SC_CTHREAD) then you will have to use the SC_HAS_PROCESS macro to indicate that your module has process/es.
And regarding nested class it is the same thing as in C++.
I am not sure what you mean by the 3rd question.
regarding your 3rd question: you can do same as you usually do in a C++ program. The best place to specify an attribute/operation's scope is the declaration part of the SC_MODULE, whether you put it in cpp or header file.
In a SystemC design, normally only the ports and constructor/destructor should be defined as public to allow other modules to connect with it, unless you have a strong reason and want to break the modularity of a systemc design to access explicitly the member functions of a module.

How to wrap a C++ class in a C based dll or a CLI based dll?

I am told to import my writen class in C++ into a dll and then use that dll in a c# application. Following this guide I created the dll, but I can't simply use it in a C# application since there are some issues concerning it:
What should I place for the return type of my factory function?
What is the equivalent of const wchar_t* which is my constructors argument type?
How can I retrieve and use my functions return type which is of type vector< wstring>?
These are the problems that prevent me from using my C++ DLL inside my C# applications. I was told that I need to create a wrapper with C++/CLI and then use that inside my C#. But sadly I have no idea about it, I don't know C++.net.
The only thing that currently seems to be a bit more sensational to me is to make it somehow compatible with C and then create a C DLL and use that in my C# application. I have read that in C, class object pointers are accessible through HANDLEs, so I thought that would be good idea to get things going without a lot of changes.
So the question is how can I use Handles to access my class objects in C and use them? And how can I convert a vector<wstring> to its C counterpart?
If I want to use CLI to create a wrapper (DLL?) for my C++ DLL, to be used in other dotnet apps what should I do?
In order to make a C wrapper for a C++ class to be used in for example a C# application you can do the following.
In Visual Studio choose Win32 Console Application and Enter a name, Then click next and on the next pane choose DLL and click finish. When you are done you are represented with a DLL project including 3 files.
testdll.h
testdll.cpp
dllmain
Delete everything that exists inside your testdll.h and testdll.cpp files and copy the following contents to each respectively. Add these lines to your testdll.h
// Our C wrapper for creating a dll to be used in C# apps
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TESTDLL_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TESTDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
extern "C"
{
TESTDLL_API int OurTestFunction(int x, int y);
}
It is inside this extern "C" block where you define your interface, functions to access your class member functions.Note the TESTDLL before the function prototype. All of your functions must be proceeded by that.
Add these to your testdll.cpp file:
#include "testdll.h"
#include "ourClass.h"
#define DLL_EXPORT
extern "C"
{
OurClass ourObject;
TESTDLL_API int OurTestFunction(int x, int y)
{
return ourObject.Add(x,y);
}
}
You compile this and get a C based dll which can be used in a C# application.
There are couple of things to notice though, The more important ones are:
You need to understand that the code you use as a proxy- i mean
function definition inside your testdll.h, must only use C
compatible types, it is C after all not C++.
is that you would want to be able to allocate new objects of your
class instead of just using one global object to access all methods.
For this, if you need to pass your class objects between member functions, you need to first convert it to a void* which C can understand and then pass it and use it to access your member functions of whatever.
For example I would have something like this inside my testdll.h in order to make user capable of managing the objects indirectly:
#ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
extern "C"
{
TESTDLL_API int OurTestFunction(int x, int y);
TESTDLL_API void* CreateHandle();
TESTDLL_API void* GetCurrentHandle();
TESTDLL_API void DisposeCurrentHandle();
TESTDLL_API void SetCurrentHandle(void* handle);
TESTDLL_API void* GetHandle();
TESTDLL_API void DisposeHandle(void*);
TESTDLL_API void DisposeArrayBuffers(void);
}
And inside my testdll.cpp I would define them as :
#include "testdll.h"
#include "ourClass.h"
#define DLL_EXPORT
extern "C"
{
OurClass *ourObject;
TESTDLL_API int OurTestFunction(int x, int y)
{
//return ourObject.Add(x,y); -- not any more !!
ourObject = reinterpret_cast<OurClass *>(GetHandle());
}
//Handle operations
TESTDLL_API void* CreateHandle()
{
if (ourObject == nullptr)
{
ourObject = new OurClass ;
}
else
{
delete ourObject ;
ourObject = new OurClass ;
}
return reinterpret_cast<void*>(ourObject);
}
TESTDLL_API void* GetCurrentHandle()
{
return reinterpret_cast<void*>(ourObject );
}
TESTDLL_API void DisposeCurrentHandle()
{
delete ourObject ;
ourObject = nullptr;
}
TESTDLL_API void SetCurrentHandle(void* handle)
{
if (handle != nullptr)
{
ourObject = reinterpret_cast<OurClass *>(handle);
}
else
{
ourObject = new OurClass ;
}
}
//factory utility function
TESTDLL_API void* GetHandle()
{
void* handle = GetCurrentHandle();
if (handle != nullptr)
{
return handle;
}
else
{
ourObject = new OurClass ;
handle = reinterpret_cast <void*>(ourObject );
}
return handle;
}
CDLL_API void DisposeHandle(void* handle)
{
OurClass * tmp = reinterpret_cast<OurClass *>(handle);
delete tmp;
}
TESTDLL_API void DisposeArrayBuffers(void)
{
ourObject = reinterpret_cast<OurClass *>(GetHandle());
return ourObject ->DisposeBuffers();//This is a member function defined solely for this purpose of being used inside this wrapper to delete any allocated resources by our class object.
}
}
And when we compile this Dll, we can easily work with it inside our C# application. Before being able to use our functions defined in this dll we need to use appropriate [ImportDll()]. So for our TestDll we would write:
[DllImport(#"TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int OurTestFunction(int firstNumber,int secondNumber);
And finally use it like:
private void btnReadBigram_Click(object sender, EventArgs e)
{
int x = OurTestFunction(10,50);
MessageBox.Show(x.ToString());
}
This is all I did to make my C++ class member functions accessible inside a C# application without any hassle.
Note:
When compiling your C# application make sure you have chosen the x86 Platform for compiling your project not AnyCpu.You can change your platform through properties.
Note 2:
For knowing how to create a C++/CLI wrapper for your native C++ class read this: C++/CLI wrapper for your native C++ class.
Using a native C++ class directly from C# is technically possible, but it's not trivial, and it's rarely even a good idea. For starters, you have to know the names to use to import from the DLL, which will be the names after C++ name-mangling. You also can't directly access things like vector from C#.
There are basically two good options:
The first is to write a DLL with a C interface that uses only types that can be marshalled into CLR types. You may use pointers along with the IntPtr type, but you can't really dereference those pointers. You can pretty much just store them in your C# code and then pass them back to the native DLL when needed. And you can also use simple struct types as long as you don't need deep copy to work on them. This option involves using P/Invoke.
The second option is to write a mixed-mode C++/CLI assembly that implements all the logic that needs to access your native code. This assembly can directly access classes and data from your C# code and also directly access your native code, although you should be forewarned that there are annoying breaks where you can't mix the two. For example, a ref class in C++/CLI can't have a shared_ptr member. However, it can have a raw C++ pointer as a member. A (mixed-mode) native class can also have access to a CLR handle type and make calls into the C# code through this. This option involves using C++ Interop.
It's worth noting that you could also go the other way with C++ Interop. You could have your C# code access a mixed-mode C++/CLI assembly that provides a .NET interface to some native code. However, you will still have to do some translation in this case so it's not hugely better than the first option.
A full tutorial on C++ Interop would be rather lengthy. I suggest you read up here and do some further investigation of C++ Interop on Google.
C++/CLI introduces managed objects, for which the pointer token * should be replaced with a ^, and a 'new' should be replaced with 'gcnew', you don't need to delete these objects when you're done with them, they'll be garbage collected, [edit] managed classes have a ref keyword in their definition [/edit].
Wrapping the C++ MyClass class in a C++/CLI wrapper class WrapperCLass could look something like this:
#include <stdio.h>
class MyClass
{
public:
void ShowStuff(const wchar_t *a)
{
wprintf(a);
}
};
public ref class WrapperClass
{
MyClass *wrapped;
public:
WrapperClass()
{
wrapped = new MyClass;
}
~WrapperClass()
{
delete wrapped;
}
void ShowStuff(IntPtr string)
{
wrapped->ShowStuff((const wchar_t *)string.ToPointer());
}
};
If you generate a dll with this, you'll be able to use it as a reference in your C# project
and you won't have to use the factory function mechanism.
In C++/CLI are available, so const wchar_t * is as wel.
To convert a System::String to a const wchar_t * you could use something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client
{
class Program
{
static void Main(string[] args)
{
WrapperClass w = new WrapperClass();
IntPtr tmp;
w.ShowStuff(tmp = System.Runtime.InteropServices.Marshal.StringToHGlobalUni("Test"));
System.Runtime.InteropServices.Marshal.FreeHGlobal(tmp);
}
}
}
(There could very well be better ways to do this...)
For your return type you'll have to do the conversion in your wrapper class. Make some .net collection, iterate through your vector, convert the wstring to a System::String, and add it to the .net collection, and return that.

JNI: Unsatisfied Link Error when passing parameters

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...