Disclaimer: I ignore pretty much everything about C++, so I hope I'm not saying stupid things here, if I am, please feel free to correct me.
As a Java developer, when I want to create a new object, I use a constructor method that will allocate this object in memory and return a handle on it for me, and I will store this handle in a variable, I do it like this.
Foo o = new Foo();
But in C++, I've been given to understand, that despite the fact it is possible to do so
Foo createFoo(){
Foo f;
f.doSomething();
return f;
}
// ...
Foo f = createFoo();
I can also define a handle by myself, and then call a initializer on it that will allocate memory and bind the handle on it, like this:
void initializeFoo(Foo **f){
f.doSomething();
return;
}
// ...
Foo f;
initializeFoo(&f);
So my question is, what happens when we want to use those C++ methods in Java, with JNA?
Let's suppose I have the following C++ header:
typedef struct Foo f;
Foo createFoo();
void initializeFoo(Foo **f);
As I don't have any idea on what a Foo is, or what the Foo structure contains, I'm just going to create a JNA PointerType to declare my structure:
public class Foo extends PointerType{
public Foo(Pointer address) {
super(address);
}
public Foo() {
super();
}
}
Using the createFoo method should be pretty easy as well:
public class TestFoo{
static{
System.loadLibrary("foolib");
}
public static void main(String[] args){
FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);
Foo f = lib.createFoo();
}
Right?
But my question is, how can I use the initializeFoo function??? I suppose I would have to create a Pointer and give it to the function, but how do I create a non NULL pointer in JNA? I tried the following code, but it results in an EXCEPTION_ACCESS_VIOLATION.
public class TestFoo{
static{
System.loadLibrary("foolib");
}
public static void main(String[] args){
FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);
Foo f = new Foo();
lib.initializeFoo(f); // EXCEPTION_ACCESS_VIOLATION
lib.initializeFoo(f.getPointer()); // EXCEPTION_ACCESS_VIOLATION
}
Any idea?
Thanks!
Foo f;
initializeFoo(&f);
initializeFoo() does not "allocate memory and bind the handle" for f, as you say. Foo f; creates f and allocates it in memory. initializeFoo() could do something like assign values to f's member properties, and the like, as well as create another Foo object and assign it to f, but it does not do what you say.
On the other hand,
Foo *f;
f = new Foo();
declares a Foo pointer. new allocates memory and creates a Foo object, and assigns the memory location to f (you can think of a pointer as a integer containing an address).
I think you want to learn more about C++ and pointers before you go any further.
As I don't have any idea on what a Foo is, or what the Foo structure contains, I'm just going to create a JNA PointerType to declare my structure
This makes it impossible to allocate memory for Foo, as you have to know how much memory you need to allocate. For c structures jna needs a java class mirroring the structure or if you at least know its size you can try to use the Memory class which has a ctor taking a size argument.
For c++ structures and classes using c++ features like inheritance this fails since the required memory and layout depends on the compiler and enabled optimisations.
Related
I have read my question one more time and I think the example was not good enought to show where was my confusion. So I will show a different example.
public class Main {
public static void main(String args[]) {
Foo foo = new Foo();
foo.deleteOtherFoo();
}
}
public class Foo {
private OtherFoo otherFoo;
public Foo() {
otherFoo = new OtherFoo();
}
public void deleteOtherFoo() {
this.otherFoo = null;
}
}
public class OtherFoo {
public OtherFoo() {}
}
If I follow what I know about stack and heap, I can say:
my draw
in the frame deleteOtherFoo what do I have as parameters? because I know I can only have primitive type or reference type value. In that case I have a reference type Foo.otherFoo ? a value that contain a pointer of a pointer ?
Because when I put this.otherFoo = null, I remove the ref of otherFoo from the object foo.
code lives in an entirely different place. Code is effectively unchanging, save some crazy 'reload this class from disk again please' shenanigans (which the JVM does support but that's an entirely different can of worms).
So where does 'the method' live? Well, nowhere. The CODE of the method lives in what used to be called permgen. It's definitely not the stack, never gets garbage collected, and no matter how many Foo objects you make, the code is located in memory only once.
And that's that.. until you call the method.
When you call the method, if it's non-static, it needs 'an instance'. This is, as far as the JVM is concerned, pretty much 100% the same as a parameter: If you call foo.doThingie(a);, then both foo and a are parameters to the doThingie method. These are put on the stack, and then doThingie is executed. Once doThingie finishes execution, the stack is reset to the point before doThingie was invoked, so, 'foo' and 'a' are now gone.
In java, all non-primitives are 'references' which is just javaspeak for 'pointers'. So when I say 'foo and a are on the stack', what I really mean is 'a pointer, into the heap, pointing at the data (i.e., the fields) that represent an instance of Foo, is on the stack'.
I am trying to simulate a kind of pointer used in another obscure programming paradigm, so I can port some code to Java. The other language is not object-oriented, and was loosely inspired by Pascal.
In the original language, we can write code like this. First, working with text.
// Start with text.
Text myVar = "Bonjour"
Pointer myPointer = ->myVar // Referencing a string variable, storing the reference in another variable of type `Pointer`.
Message( myPointer-> ) // Dereferencing the pointer, to retrieve `myVar`, and pass the string to a command `Display` that displays the message on screen in a dialog box.
Then, switching to numbers.
// Switch gears, to work with an number.
Integer vResult = ( Random % ( vEnd - vStart + 1 ) ) + vStart // Generate random number.
myPointer = ->vResult // The same pointer now points to numeric variable rather than a textual variable.
We can assign a pointer by the text of a variable name.
myPointer = Get pointer( "var" + String($i) ) // Generate pointer variable named `var1`, or `var2`, etc.
We can ask the pointer for a code number representing the data type of the value to which it is pointing (the data type of the referent).
typeCodeNumber = Type( myPointer ) // Returns 11 for an integer, 22 for text.
In this other language, the compiler does provide for type-safety. But when using pointers in this fashion, we sacrifice type-safety. The compiler emits a warning that the code usage is ambiguous with regard to type.
My idea to port this code is to define a XPointer class as well as classes for the types such as XText and XInteger.
I need to hold a reference to an object of any of a dozen specific known types, including to another pointer. I can hard-code the dozen types, no need to be open to all types.
These dozen types do not share an interface nor abstract class other than Object. And even if they did share an interface/superclass, I do not want them returned as a superclass but as their original concrete class. As they entered the pointer, so should they emerge from the pointer.
My current plan is to define a XPointer class in Java with a pair of reference and dereference methods:
XPointer::ref( x ) where you pass an object of Dog, Truck, or Sculpture class, or even another XPointer object.
XPointer::deref ⇒ x where x is an object recognized as its original type, a Dog, a Truck, or a Sculpture or even another XPointer object, rather than a mere Object object.
➥ Is there some way to do this Java? Perhaps with Generics?
➥ If not possible in Java, I could reluctantly switch to Kotlin. Can this pointer functionality can be done in Kotlin running on a JVM?
So code my look like this:
XPointer p = new XPointer() ; // Points to nothing, null.
p.ref( new Dog() ) ; // Pointer points to a `Dog` object.
p.deref().bark() ; // Pointer can retrieve the `Dog` as such, a `Dog` object.
p.ref( someTruck ) ; // The pointer can switch to pointing to an object of an entirely different type. The `Dog` object has been replaced by a `Truck` object.
p.deref().honk() ; // Dereference the stored `Truck` object as such.
And a pointer to a pointer.
XPointer p2 = new XPointer() ; // Points to nothing, null.
p2.ref( p ) ; // 2nd pointer points to a pointer that points to a `Truck` object.
p2.deref().deref().honk() ; // Dereference the stored `Truck` object as such.
If there is a better route towards such a pointer-simulation, I am open to suggestions. Elegance is not required; any hack will do.
This is known as a union or a variant type (see Boost.Variant in C++). The latter is specially handy as it's a type-safe container for a heterogeneous set of types and stands the closest to your description of a type of code you are porting from. Since Java does not support templates - no, generics are not templates - you won't get exactly what you are looking for.
The Optional type is the simplest case of two types: a type T and a Null. Given your requirement to store more than a type T or Null, it won't work for you.
You may want to check out the JavaSealedUnions. In addition, Kotlin provides a concept of sealed classes, helpful to limit a value to one of the types from a constrained set.
Good luck!
My apologies for the long answer.
I don't think you can achieve exactly what you want with Generics without losing type safety.
For the next line to work, Java needs to know there is a Truck returned by the defer() method so it can call honk() on that object.
p.deref().honk();
But if you would use Java Generics, than that infers type erasure on compilation.
The solution would imply adding a generic type like Pointer<Truck>, but we can't since you want to be able to add a dozen specific known types and a Pointer.
However ... since you yourself write that line like that, specifically making a call to bark() or honk(),
it implies you already know that the Pointer references a Dog or Truck object at that point in your code.
Using that assumption, Generics and a modification to defer(), you can get pretty close to a solution.
Let's say we have these classes, which have no links in any way.
public class Dog {
public void bark() {
System.out.println("Bark ...");
}
}
public class Truck {
public void honk() {
System.out.println("Honk ...");
}
}
Then we need a Pointer class like this, where the deref() method needs a Class parameter to know which type to return.
public class Pointer {
private Object myObj;
public <T> void ref(T myObject) {
this.myObj = myObject;
}
public <T> T deref(Class<T> myClazz) {
try {
return myClazz.cast(myObj);
} catch(ClassCastException e) {
return null;
}
}
}
Then you can do the following
public static void main(String[] args) {
Pointer pointer = new Pointer();
Dog dog = new Dog();
pointer.ref(dog); // Reference to a Dog
pointer.deref(Dog.class).bark();
Truck truck = new Truck();
pointer.ref(truck); // Reference to a Truck
pointer.deref(Truck.class).honk();
Pointer subPointer = new Pointer();
pointer.ref(subPointer); // Reference to another pointer
subPointer.ref(truck); // Other pointer references a Truck
pointer.deref(Pointer.class).deref(Truck.class).honk();
subPointer.ref(dog); // Other pointer references a Dog
pointer.deref(Pointer.class).deref(Dog.class).bark();
pointer.ref(null); // Clears the reference
Truck bulldog = new Truck();
pointer.ref(bulldog);
pointer.deref(Dog.class).bark(); // Is allowed, but will cause a NullPointerException
}
This will print out:
Bark ...
Honk ...
Honk ...
Bark ...
Exception in thread "main" java.lang.NullPointerException at Pointer.main(Pointer.java:39)
If you need to limit your Pointer reference to only your dozen specific known types and the Pointer class itself, then you need to extend them with a super class (for example Pointerable) and modify the ref() method accordingly.
Then you can prevent types that don't extend this super class to be referenced by your Pointer.
Example:
public abstract class Pointerable { }
public class Dog extends Pointerable {
public void bark() {
System.out.println("Bark ...");
}
}
public class Pointer extends Pointerable {
private Object myObj;
public <T extends Pointerable> void ref(T myObject) {
this.myObj = myObject;
}
public <T extends Pointerable> T deref(Class<T> myClazz) {
try {
return myClazz.cast(myObj);
} catch(ClassCastException e) {
return null;
}
}
}
This is the best I can come up with. I think you can't easily make a common Type, without it being the parent of all classes (like Object).
Also conversion is hard given the type system, you can possibly mimic it by not allowing to reassign pointers of different type, but just generating a new pointer every time you do a get. if you don't like to know the type itself you can use var in modern java to hide the type difference.
public class Types {
public static void main(String[] args) {
var p = new PascalPointer<>(new PascalInt());
PascalInt i = p.get();
var p2 = new PascalPointer<>(i.toPStr()); // mimic generics by type inference.
PascalString s = p2.get();
PascalPointer<PascalType> genericPointer = new PascalPointer<>(s);
genericPointer.set(i);
var i2 = (PascalInt) genericPointer.get();
}
public interface PascalType { }
public static class PascalInt implements PascalType {
// cast
public PascalString toPStr() {
return new PascalString(); // hide a new to do a conversion instead of a cast really.
}
}
public static class PascalString implements PascalType { }
public static class PascalPointer<T extends PascalType> {
T t;
public PascalPointer(T t) { this.t = t; }
public T get() { return t;}
public void set(T t) {this.t = t;}
}
}
This probably breaks down when you want to have an Int view of a string and you update the string (as I am copying here).
The cast to Bar is necessary in this code. I'm trying to understand what problem it avoids. If the compiler would let me use the Foo as a Bar without casting, would it not be able to use the extended functionality that Bar could have? Or is there some more important reason? Or is the example too trivial to explain why I must cast?
class Foo { }
class Bar extends Foo { }
public class Main {
public static void main(String[] args) {
Foo f1 = new Bar();
Bar b1 = (Bar) f1;
}
}
Can we write a simple example where I see and understand that if I don't cast there will be trouble? I could think that the runtime could help itself without casting in the code above, but certainly I have not understood the deep details why I must do the casting.
This protects you from wrong casting. If you will want to use not casted class, which actually is now of type Bar what you will expect to see when using its method? For example you actually make f1 of type Foo, and then you try to make b1 of type Bar point to class Foo. You are trying to invoke method from Bar, but there is no implementation of it. What you expect? Compiler won't know either. In this case if you are trying to cast wrong class you will obtain just java.lang.ClassCastException, which we know how to protect from.
The necessity of the cast becomes more clear if you add another class to your hierarchy. Consider this set of classes instead:
class Foo {}
class Bar extends Foo {}
class Baz extends Foo {}
Now if you have a reference of type Foo, it may refer to a Foo instance, a Bar instance, or a Baz instance. Consider this code snippit:
Foo f;
if (Math.random() > 0.5) {
f = new Bar();
} else {
f = new Baz();
}
You can't simply call f a Bar, because it may be the case that f isn't a Bar, but rather a Baz. Hence, the cast is essentially saying , "I know there's a chance this may fail, but I have reason to believe it won't so go ahead and try it". For example, we could do the following:
Foo f;
if (Math.random() > 0.5) {
f = new Bar();
} else {
f = new Baz();
}
if (f instanceof Bar) {
Bar b = (Bar) f;
// do stuff with b...
}
Within the if block, we have reason to believe that f is a Bar instance, even though the java compiler can't be sure of that. (In this example it seems trivial, but there could be thousands of lines and multiple stack frames separating the if condition and the cast). Hence, we can make the cast with confidence.
If, however, you're wrong about that, that the cast is in fact not valid, you'll get a ClassCastException on the line where the cast was attempted. This makes the issue more clear: instead of getting the exception on a random line where the instance in question doesn't have the desired functionality, it happens where the conversion was attempted.
I need to get some clarification on Java references (pointers).
I have read this (Java is Pass-by-Value, Dammit! by Scott Stanchfield) excellent write up on Java's way of passing variables around. As far as I understand everything is passed around as memory pointers.
public class foo{
int a;
int b;
public foo(a, b){
this.a = a;
this.b = b;
}
}
so in some code like this:
foo aFoo = new foo(1,2); //new foo created at adress 0x40 for instance
someFunc(aFoo);
the argument to someFuncis actually the number 0x40 (albeit this might be a simplification, but to get a sense for the pattern).
Now, suppose i created another class
public class bar{
foo aFoo;
public bar(){
this.aFoo = new foo(1,2);
}
}
and instantiated the following variables
bar aBar = new bar();
foo bFoo = new foo(3,4);
now suppose i want to copy the values of aBar.aFoo into bFoo like
bFoo = aBar.aFoo;
If i now do
bFoo.a = 1234;
did i also just change aBar.aFoo.a into 1234 or does that variable still hold the value 1?
By my own logic, bFoo.a is just a pointer, so assigning a new variable should alter both places, but this seems incorrect. So I guess i have not fully understood Java's "reference is really a pointer" concept. Or rather, i might understand the pointer part of it, but not the dereferencing of the pointers, since this is done implicitly compared to in C where you always know.
bFoo = aBar.aFoo;
-> you have assigned the aBar.aFoo reference to bFoo local variable. This is called aliasing because now you have two ways to refer to the same object: bFoo and aBar.aFoo.
bFoo.a = 1234;
-> you have assigned 1234 to the a field of the object referred to by bFoo. This object is referred to by aBar.aFoo as well.
Result: you have changed the value of aBar.aFoo.a.
I want to use reference in Java but I don't know how!
for example in C++ we write:
void sum(int& x)
{
...
}
but in Java & sign is a compiler error!
please help me to understand references in Java.
Objects are passed by reference by default Objects are accessed by reference, but there is no way to create a reference to a primitive value (byte, short,int, long). You either have to create an object to wrap the integer or use a single element array.
public void sum(int[] i){
i[0] = ...;
}
or
public void sum(MyInt i){
i.value = ...;
}
public class MyInt{
public int value;
}
for your example something like the following could work
public int sum(int v){
return ...;
}
or
public int sum(){
return ...;
}
Update:
Additional/Better description of object references:
Java Objects are always accessed by a reference. Like the primitive types this reference is passed by value (e.g. copied). Since everything a programmer can access in java is passed by copying it (references, primitives) and there is no way to create a reference to a primitive type, any modification to a method parameter (references, primitives) only affects the local copy within the method.
Objects can be modified within a method since both copies of the reference (local and other) still point to the same object instance.
example:
Modify a primitive within method, this only affects the internal copy of i and not the passed value.
void primitive(int i){
i = 0;
}
Modify a reference within method, this only affects the internal copy of ref and not the passed value.
void reference(Object ref){
ref = new Object();//points to new Object() only within this method
}
Modify an object, visible globally
void object(List l){
l.add(new Object());//modifies the object instead of the reference
}
Both the array and MyInt above are based on the modification of an object.
An ordinary Java parameter already is closer to a C++ reference than to C++ pass-by-value or pass-by-pointer. So, all your Java methods are already like this.
int and other primitives are special in Java, however; the above is true for object references.
Edit: More precisely, as stated #fatih, all Java invocations are pass-by-value. However, when you pass an object you are passing a reference by value. So, as a first approximation, the above statement is correct: An ordinary Java parameter is more similar to a C++ reference than to C++ pass-by-value or pass-by-pointer.
Required reading on understanding Java's Pass By Value semantics:
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
http://javadude.com/articles/passbyvalue.htm
http://javachannel.net/wiki/pmwiki.php/FAQ/PassingVariables (links to several other pages)
Completely remove the notion from your head that Java can have anything passed by reference. Let's look at an example, shall we?
public class App
{
public static void main( String[] args )
{
Foo f1 = new Foo();
doSomethingToFoo(f1);
System.out.println(f1.bar); //Hey guess what, f1.bar is still 0 because JAVA IS PASS BY VALUE!!!
}
static void doSomethingToFoo(Foo f) {
f = new Foo();
f.bar = 99;
}
static class Foo {
int bar = 0;
}
}
The MutableInt class in Apache Commons will do what you want, although it's not pretty.
MutableInt
void sum(MutableInt mx)
{
int x = mx.getValue();
x = ...
mx.setValue(x);
}
...
MutableInt mx = new MutableInt(5);
sum(mx);
int result = mx.getValue();
Additional classes are provided for other primitive types, and also for objects.
There is some overhead involved in creating an additional object simply to provide a reference, so the solution is not optimal, but in most cases you should be ok.
In general, it is always best to find a way to return a result from a method. Unfortunately, Java only allows one value to be returned in this way.