Odd question here not quite sure how to ask it.
I am writing some JNA bindings for a proprietary shared library.
the library api has several functions named things like km_open, km_close, etc.
In c, these functions are defined in the header file as such:
Komodo km_open (
int port_number
);
int km_close (
Komodo komodo
);
and in Java i made JNA bindings for them defined like this:
public abstract Komodo km_open(int port_number);
public abstract int km_close(Komodo komodo);
but JNA fails to find these symbols in the library.
When I dump the symbols in the binary
i find the following:
0000000000008e20 g DF .text 0000000000000005 Base net_km_open
0000000000007410 g DF .text 0000000000000005 Base c_km_open
0000000000008e40 g DF .text 0000000000000005 Base net_km_close
0000000000007430 g DF .text 0000000000000005 Base c_km_close
I am guessing that because this library is meant to be used by both .net and standalone c applications that these names are mangled to provide alternative versions of the function. and yet I cannot find anything in the demo applications source code that maps the name c_km_open to km_open. yet it compiles in GCC and the code works. How do these symbols get resolved when linking/loading the binary and does JNA have a method of doing the same thing? Currently I can get the JNA bindings to work if I modify the bindings like this:
public abstract Komodo c_km_open(int port_number);
public abstract int c_km_close(Komodo komodo);
which is an acceptable workaround I just want to understand what is going on in the background here.
Nevermind, I found the answer, it was kind of tricky, but instead of linking against the .so library file itself, the makefile generated a piece of object code by the same name as the .so library which defined wrapper methods that dynamically loaded the "c_" functions. they then linked to that piece of object code instead of the library. it didn't come up in a search because it was a generated file.
The solution in JNA is then to simply mimic that behavior by creating a wrapper class with the simplified names that make a callback to the JNA bindings
Related
Coming from a C++ environment I got used to splitting up many of the functions that I needed into an funcs.h file and then do #include "funcs.h" and then adding the functions prototypes into the main .cpp file.
Now I am starting to work with Java (mainly with Minecraft ModloeaderMp), and I already made a funcs.java file where there are some premade functions (e.g., some functions for file copying, giving stacks of items, etc.). Since I am already using the statement Public class mod_mine extends BaseModMp, is there a way I can import the functions or do I can I just do another Public class mod_mine extends funcs?
You don't #include in Java; you import package.Class. Since Java 6 (or was it 5?), you can also import static package.Class.staticMethodOfClass, which would achieve some forms of what you're trying to do.
Also, as #duffymo noted, import only saves you from systematically prefixing the imported class names with the package name, or the imported static method names with the package and class name. The actual #include semantics doesn't exist in Java - at all.
That said, having a "funcs.java" file seems to me like you are starting to dip your toes into some anti-patterns... And you should stay away from these.
There's no #include in Java.
I would not like a design that had a funcs.java that stored all the variables. Objects are state and behavior encapsulated into a single component. You aren't designing in an object-oriented way if you do that.
Good names matter. A class named Stuff that extends Stuff2 had better just be a poor example.
That's not good Java. I wouldn't consider it to be good C++, either.
It sounds like you're putting all your methods in the same class. You should separate them:
Utility classes
These should contain static methods that do things like get the contents of a file, show a dialog screen, or add two numbers together. They don't really belong in an object class, they don't require instances, and they're used widely throughout the program. See java.lang.Math for a good example of this.
Constant class or configuration files
This can be a Constants class that contains static final members, like PI = 3.1415. You can access them using Constants.PI.
Or, you can use configuration files and load them into Configuration and access the configuration variables with something like config.get("database").
Other
If your code doesn't fit into any of these, you will want to put it into some class such that your code fits object-oriented programming concepts. From your question, it sounds like you'll want to read up on this. I would first read Head First Java, then maybe some other books on object-oriented programming in Java. After that, I'd look at some design patterns.
Java is an object-oriented programming language, and there is a reason for it.
There isn't any #include in Java, although you can import classes from other packages.
Making separate class, func.java, to store variables might not be a good idea, until or unless all of them are constants.
By extending some class, you can reuse the function. But does extending class pass the is a test? If not that, this might be a bad idea.
If moving from C++, going through some good book, for example, Head First Java might help a lot.
There isn't any #include in Java. You can use the import statement to make classes and interfaces available in your file.
You can run the C preprocessor on a Java file, ensuring you use the -P flag to disable line annotations. A quick Google search confirms that this has been attempted at least twice, and is even used in the popular fastutil library:
Using C style macros in Java
https://lyubomyr-shaydariv.github.io/posts/2016-09-06-fun-with-java-and-c-preprocessor/
This works for all directives (#include, #define, #ifdef, and so forth) and is both syntactically and semantically identical to the equivalent statements in C/C++.
Actually... There is a way to have the same semantics as in C's #include (the keyword was later borrowed by C++ for the sake of looking fancy...). It's just not defined with the same words, but it does exactly what you are looking for.
First, let's see what you do with #include in C++ to understand the question:
include #defines,
"forward" function definitions (their "body" being defined elsewhere, in a class implementation, if you remember Turbo Pascal, you get my point),
define structures,
and that's pretty much it.
For the structure definitions, there isn't any point. That's old-school C: in C++ you don't define struct {} anymore for ages; you define class structures with properties and accessor methods. It's the same in Java: no typedef struct {} here either.
For this, you have the "interface" declaration (see Interfaces (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)):
It does exactly what you're looking for:
public interface MyDefines {
final CHAR_SPACE : ' '; // ugly #define
int detectSpace(FileInputStream fis); // function declaration
// and so on
}
Then, to use:
public class MyClass extends MyAncestor implements MyDefines {
...
// implementation of detectSpace()
int detectSpace(FileInputStream fis) {
int ret = 0;
char Car;
if((Car = fis.read()) != -1) && (Car == CHAR_SPACE)) ret++;
...
}
Read the link given above; it's full of useful cases.
I am using RAD Studio 10.2 Tokyo and am programming in Delphi.
I am having general problems with a Java object using the JNI libraries.
What I am trying to do is find the maximum audio amplitude of an Android audio source between button presses.
Here is the code that I am using.
var
Form1: TForm1;
Recorder: JMediaRecorder;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not assigned(Recorder) then
begin
Recorder:= TJMediaRecorder.Create();
Recorder.setAudioSource(1);
Recorder.setOutputFormat(1);
Recorder.setAudioEncoder(1);
Recorder.setOutputFile(TPath.GetTempPath+'/test');
Recorder.prepare();
Recorder.start();
end;
Label1.Text:=IntToStr(Recorder.getMaxAmplitude());
end;
This appears to generate multiple issues.
Issue #1:
Although I am aware that in java the Media recorder settings should look something like
Recorder.setAudioSource(MediaRecorder.AudioSource.MIC).
That is not something that I can enter in RAD Studio. I took a look at the API and found that that is supposed to mean an integer of 1. The problem is that it gives me an error saying that it can't find an audio source.
Issue #2:
I need to set a path for the file using
Recorder.setOutputFile()
The problem with this is that it only accepts JStrings as input. I have looked all over the place and found a few people who use
StringToJString('my super cool string')
I think this is a part of a library that I am unaware of though because it doesn't work when I use it.
If you know of another way to get an amplitude reading off an Android audio source I would also accept that as an answer as that is the overall problem I am trying to solve.
In general, within the Delphi Android JNI framework:
Java class types are represented in Delphi using classes that are prefixed with TJ, and Java object instances are represented in Delphi using interfaces that are prefixed with J.
nested Java classes are represented by Delphi classes and interfaces that are named after the parent class name followed by _ followed by the nested class name.
Java static constants/fields/properties/methods are represented in Delphi as sub-properties/methods of a special JavaClass class property.
So, in your case:
the Java MediaRecorder class is represented by the TJMediaRecorder class and JMediaRecorder interface.
the Java MediaRecorder.AudioSource class is represented by the TJMediaRecorder_AudioSource class and JMediaRecorder_AudioSource interface.
the Java MediaRecorder.AudioSource.MIC constant is represented by the TJMediaRecorder_AudioSource.JavaClass.MIC class property:
Recorder.setAudioSource(TJMediaRecorder_AudioSource.JavaClass.MIC);
The same thing applies to the MediaRecorder.setOutputFormat() and MediaRecorder.setAudioEncoder() methods:
Recorder.setOutputFormat(TJMediaRecorder_OutputFormat.JavaClass.THREE_GPP);
Recorder.setAudioEncoder(TJMediaRecorder_AudioEncoder.JavaClass.AMR_NB);
As for strings, JNI knows nothing about Delphi strings, so you must use StringToJString() to convert Delphi strings to JNI strings, and use JStringToString() to convert JNI strings to Delphi strings. Both functions are in the Delphi RTL, specifically in the Androidapi.Helpers unit (XE6+) or Androidapi.JNI.JavaTypes unit (XE5), depending on which version of Delphi you are using.
Recorder.setOutputFile(StringToJString(TPath.Combine(TPath.GetTempPath, 'test')));
Is there a way of using reflection to create a class programmatically? For instance. Is there a private constructor we can use to create a class type that then can be used to create instances of that class?
I know that there are other tricks like generating source code and compiling it, or generating byte code and loading it using a classloader... But I want to see if it is possible to somehow create an instance of java.lang.Class directly.
I want to write the following code in clojure:
(def c (create-class "com.example.Dog" {:fields {"legs" 4}
:methods {"bark" (... do something ...)}
:constructors {.....}}))
(def d1 (.newInstance c))
(def d2 (.newInstance c))
Clojure has several ways to generate classes depending on your needs: They are described in the Clojure types page Though I found the chapter on types in Clojure Programming most helpful as a comparison of the various ways of generating classes dynamically.
defrecord
deftype
proxy
gen-class
protocols
reify
Under the hood these generate bytecode and load it using a classloader (except for gen-class) which writes class files. There is a lot more to the subject than I can cover here, it's well worth checking out the chapter in Clojure Programming (or your favorite Clojure Book)
I wrote a set of C++ classes and created a DLL that exports one of these C++ classes. I need to instantiate the exported C++ class in a Java class. Is that possible?
I searched the web for a possible solution, but all I have found where solutions using JNA or JNI that import C++ functions only.
Yes, you can instantiate a C++ class from Java.
One way is with SWIG, which can generate Java wrappers for C++ classes.
For example, given a C++ class like this:
class MyClass {
public:
MyClass();
int myMethod( int arg );
}
SWIG allows you to write Java code like this:
MyClass myclass = new MyClass();
int val = myClass.myMethod( 42 );
If you want to instantiate a C++ class from Java, you'll have to write a little glue code (in C++) that instantiates the desired object. Further, you'll need a Java class that corresponds to the C++ class, and you need to have the glue code convert the C++ object into an object of the Java class aforementioned, and keeps them together (i.e., changes to the C++ object should reflect to the Java object, and the other way around).
This tutorial seems to have some pointers how you could do that. Specifically, it tells you how to instantiate a Java object, which is what you will need for the above approach.
I want to know if i can link and compile source code file with an object file of a class without including class source files.
Or
Like in Java i can give a compiled *.class file to a friend and the doc of that class without giving the source code and he can include that class for his need without knowing the real source.
Can i do the exact thing with C++ ? and How ?
FYI:I'm using MinGW.
I'm quite new to so this may look like a dumb question (but still there's no dumb questions).
In C++ you can just produce an executable file (.exe in windows, usually no extension in Linux) or a library file (.lib or .a) or a shared libarary (.dll or .so) depending on what you want to achieve.
If you are providing a library, you will have to provide a header file with the class declarations as well. If you don't want to give out too much about the details, you can have a "implementation" class that is simply a pointer to the implementation in your header file, and the real implementation is only available to you as the owner of the sources.
For more information, you should look up "PIMPL" as Thomas Matthews suggested - that's short for "Pointer to IMPLementation class". Basically, your "public" class is just a shell providing the functions you want others to see, and the implementation class inside it does all the hard work.
Simple example
In your header file:
// Forward declaration of the implementation class.
class double_it_impl;
// Class that stores an integer, and doubles it each time you
// call doubling().
class Public_double_it
{
public:
public_double_it(int x); // COnstructor.
int doubling(); // Function d
private:
double_it_impl *pImpl;
};
In your source or private header file, we declare the actual implementation:
class double_it_impl
{
public:
double_it_impl(int x) : m_x = x; {};
int doubling() { m_x *= 2; return m_x; }
}
public_double_it::public_double_it(int x)
{
pImpl = new public_double_it(x);
}
int public_double_it::doubling()
{
return pImpl->doubling();
}
Now you can't see what the implementation class contains or how it works - of course, this is a very trivial example, but I hope it conveys the idea.
You can give them the *.class but they can be decompiled.
Most libraries are provide using the classes and the generated Javadoc.
You could compile the class into a library or dll or shared library and give to your friend.
They would need a header file that defines the interface.
See also PIMPL idiom.
Yes, you can provide a compiled object file and documentation and others can link the .o (or .obj) file into their code. The exact details of how to do this vary between compilers and development environments. If you are using g++, you simply use the following command-line:
g++ -c source.cpp
This will create a .o file which you (or anyone else) can then link with other .o files with
g++ main.o source.o
Other compilers will have similar options. Read the help files and other documentation for instructions about how to create object files.
For a large number of functions and/or classes, you should look at creating a library file. These can be statically or dynamically linked. I suggest that you search the Web for more information if you want to learn about how to create your own library files.