Closed phanthanhliem closed 9 years ago
There's a discussion about that at issue https://github.com/bytedeco/javacpp/issues/22. Let me know if that doesn't answer the question.
Ah same guy, so I guess it doesn't answer your question. So, what is the question? Could you provide more details about what steps you are taking, what errors you are getting, etc? Thanks
Hi Saudet,
Sorry for my incomprehensible question. The problem is when I used typedef like this:
typedef std::vector<double*> Vector_p_Double;
struct structTimeSeriesResults
{
Vector_p_Double vpd_result;
...
}
There is an error when I compile:
which tells that javacpp cannot convert from Vector_p_Double to std::vector<double *,std::allocator<_Ty>> *
. It seems that javacpp does not understand the new type Vector_p_Double defined by the typedef command.
Without using typedef std::vector<double*> Vector_p_Double;
, or more exactly using directly std::vector<double*>
it works fine like in https://github.com/bytedeco/javacpp/issues/22
So the question is how could I use typedef std::vector<double*> Vector_p_Double;
?
Hope that you understand my question now.
Thank you for your help. Thanh Liem.
Ok... Would you have a complete self-contained example that I could try to run here? Thanks!
Hi Samuel, I've send a self contained example to your email. Thanks for your help.
I mean some small code example, of less than 100 lines...
Hi Samuel
This is the header spider.h
#ifndef SPIDER_H
#define SPIDER_H
#ifdef SPIDER_CPP_LIBRARY
#define SPIDERDLL_API __declspec(dllexport)
#else
#define SPIDERDLL_API __declspec(dllimport)
#endif
namespace Spider_CPP {
class spider {
public:
SPIDERDLL_API spider();
SPIDERDLL_API Struct_Simulation_Results * runSingleSimulation(std::string Simulator_Parameters_Full_File_Name);
}
}
typedef std::vector<double> Vector_Double;
struct Struct_Simulation_Results
{
Simulation_Flag Flag;
structTimeSeriesResults * s_timeSeriesResults;
Vector_Double vd_Indicators;
};
enum Simulation_Flag
{
Simulation_OK = 0,
Initialisation_Failed = 1,
Simulation_Failed = 2
};
typedef std::vector<double*> Vector_p_Double;
struct structTimeSeriesResults
{
Vector_p_Double * vpd_result;
double* p_time;
int nbPoints;
};
And the javacpp source code, testspiderdll.cpp
@Platform(include={"spider.h"}, link="SPIDER")
@Namespace("Spider_CPP")
public class testspidercpp {
public static class spider extends Pointer {
static {
System.loadLibrary("jnitestspidercpp");
}
public spider() { allocate(); }
private native void allocate();
public native Struct_Simulation_Results runSingleSimulation(@StdString String Simulator_Parameters_Full_File_Name);
}
@Namespace("")
public static class Struct_Simulation_Results extends Pointer {
static { Loader.load(); }
public Struct_Simulation_Results () { allocate(); }
private native void allocate();
public native @Cast("Simulation_Flag") int Flag(); public native Struct_Simulation_Results Flag(@Cast("Simulation_Flag") int Flag);
public native structTimeSeriesResults s_timeSeriesResults(); public native Struct_Simulation_Results s_timeSeriesResults(structTimeSeriesResults s_timeSeriesResults);
public native @StdVector DoublePointer vd_Indicators(); public native Struct_Simulation_Results vd_Indicators(@StdVector DoublePointer vd_Indicators);
}
@Namespace("")
public static enum Simulation_Flag {
Simulation_OK(0), Initialisation_Failed(1), Simulation_Failed(2);
private int value;
private Simulation_Flag(int value) {
this.value = value;
}
public static Simulation_Flag fromInt(int v) {
return Simulation_Flag.values()[v];
}
public Simulation_Flag getType() {
return Simulation_Flag.fromInt(nativeGetType());
}
private native @Name("getType") int nativeGetType();
}
@Namespace("")
public static class structTimeSeriesResults extends Pointer {
static { Loader.load(); }
public structTimeSeriesResults () { allocate(); }
private native void allocate();
public native VectorDoublePointer vpd_result(); public native structTimeSeriesResults vpd_result(VectorDoublePointer vpd_result);
public native DoublePointer p_time(); public native structTimeSeriesResults p_time(DoublePointer p_time);
public native int nbPoints(); public native structTimeSeriesResults nbPoints(int nbPoints);
}
@Namespace("")
// std:::vector<double*> in the line below works fine
//@Name("std::vector<double*>") public static class VectorDoublePointer extends Pointer {
@Name("Vector_p_Double") public static class VectorDoublePointer extends Pointer {
static { Loader.load(); }
public VectorDoublePointer(Pointer p) { super(p); }
public VectorDoublePointer(DoublePointer ... array) { this(array.length); put(array); }
public VectorDoublePointer() { allocate(); }
public VectorDoublePointer(long n) { allocate(n); }
private native void allocate();
private native void allocate(@Cast("size_t") long n);
public native @Name("operator=") @ByRef VectorDoublePointer put(@ByRef VectorDoublePointer x);
public native long size();
public native void resize(@Cast("size_t") long n);
@Index public native @Cast("double*") DoublePointer get(@Cast("size_t") long i);
public native VectorDoublePointer put(@Cast("size_t") long i, DoublePointer value);
public VectorDoublePointer put(DoublePointer ... array) {
if (size() != array.length) { resize(array.length); }
for (int i = 0; i < array.length; i++) {
put(i, array[i]);
}
return this;
}
}
public static void main(String[] args) {
spider dllInstance = new spider();
System.out.println("spider.dll is successfully loading!!\n");
String simulator_param_fullpath = "C:\\Users\\tp242786\\MyPostdoc-INES\\SPIDER\\SPIDER Qt5.4.2_MSVC2013_64bit\\Plant_And_Controls.parameters";
dllInstance.runSingleSimulation(simulator_param_fullpath);
}
}
So how could i write the javacpp code for using:
typedef std::vector<double> Vector_Double;
typedef std::vector<double*> Vector_p_Double;
Hope that these source codes is enough for you to reproduce a running example. Thanks for your support.
Vector_Double
and Vector_p_Double
are declared in the Spider_CPP
namespace, so their effective types are Spider_CPP::Vector_Double
and Spider_CPP::Vector_p_Double
, respectively. They are NOT Vector_Double
and Vector_p_Double
.
Hi Samuel,
No, Vector_Double and Vector_p_Double are NOT declared in the Spider_CPP namespace. In fact, Spider_CPP namespace contains just this:
namespace Spider_CPP {
class spider {
public:
SPIDERDLL_API spider();
SPIDERDLL_API Struct_Simulation_Results * runSingleSimulation(std::string Simulator_Parameters_Full_File_Name);
}
}
I put @Namespace("")
to escape the Spider_CPP namespace,
and this works well for other structs.
So do you have an example with the typedef structure?
Thanks and best regards.
Hi Samuel,
It's ok now, in the spider.h, I need to declare like this
Vector_p_Double * vpd_result;
instead of
Vector_p_Double vpd_result;
So, vpd_result must be declared like a pointer, which is compatible with the javacpp source code:
@Name("Vector_p_Double") public static class VectorDoublePointer extends Pointer { ...}
I have one more question, if I don't want to use the pointer * in C++,
so I got `Vector_p_Double vpd_result;
.
How do I define the class VectorDoublePointer in javacpp now?
Thanks for your support.
I see, well I just tried your example here and after fixing a few issues with your C++ code, it works just fine with Vector_p_Double
. So, I still don't understand what the issue is. Please provide some sample code so that I can reproduce the issue here. Thank you.
Hi Samuel,
Thanks for your patient. I will reexplain the problem :
With the definition of VectorDoublePointer in testspidercpp.java,
@Name("Vector_p_Double") public static class VectorDoublePointer extends Pointer { ...}
you could only declare Vector_p_Double * vpd_result;
in C++ because VectorDoublePointer extends the class Pointer. Otherwise, a definition without pointer *
, for example Vector_p_Double vpd_result;
will cause an error in the compilation.
However, the C++ code in my project is developped by some one else, so in this case, I have to insert the pointer notation *
, for example, before all the struct defined in the C++ module.
- Struct_Simulation_Results * spider::runSingleSimulation(std::string Simulator_Parameters_Full_File_Name)
- Struct_Simulation_Results * s_simulationResults
- Vector_p_Double * vpd_result;
- ...
So the question is how could I redefine the class VectorDoublePointer or structTimeSeriesResult
to remove the usage of the pointer *
in the C++ side. Or Which predefined class should I extend instead of Pointer
. If this is possible, do you have an example? In javacpp-presets, most classes extend Pointer
.
Hope that my question is clearer now. Thanks for your help.
Ah I see. Because it's just a typedef we can simply use the original name std::vector<double*>. They are just synonyms!
Hi Samuel,
The problem of using Vector_p_Double
or std::vector<doubble*>
is OK now.
In fact, using one of these two definitions is OK, we got the same result:
@Name("Vector_p_Double") public static class VectorDoublePointer extends Pointer { ...}
@Name("std::vector<double*>") public static class VectorDoublePointer extends Pointer { ...}
However in C++ side, I have to declare a pointer (ex: Vector_p_Double * vdp
or std::vector<double*> * vdp
), because the class VectorDoublePointer extends Pointer class.
I can not declare a variable without pointer like this Vector_p_Double vdp
or std::vector<double*> vdp
.
My problem is: I want to use a var without pointer in C++ side (Vector_p_Double vdp
or std::vector<double*> vdp
), and how could I change correspondingly the definition of class in javacpp. In this case, the old definition of VectorDoublePointer which extends Pointer doesn't work anymore, there will be always a compilation error.
Hope that it is clearer for you, Samuel.
For something like this:
typedef std::vector<double*>* Vector_p_Double;
Vector_p_Double vdp();
Of course we can do something like this:
@Name("std::vector<double*>") public static class VectorDoublePointer extends Pointer { ... }
public static native VectorDoublePointer vdp();
That works just fine, no problem. So, your question must be about something else.
Hi Samuel,
Sorry, :D, I don't know how to explain my prob clearer.
I need to use this declaration in C++:
typedef std::vector<double*> Vector_p_Double;
But the code in javacpp which I found in the preset
@Name("std::vector<double*>") public static class VectorDoublePointer extends Pointer { ... }
just support some thing like this:
typedef std::vector<double*> * Vector_p_Double;
How could I modify the class definition in javacpp code? For example, by removing extends Pointer
, we need to change many things in the body ?
typedef has no effect on Pointer, or vice-versa: the issue is something else...
Hi Samuel,
Yes, the prob is not typedef.
But between
typedef std::vector<double*> Vector_p_Double;
and
typedef std::vector<double*> * Vector_p_Double;
The difference here is Vector_p_Double
vs * Vector_p_Double
The second one is ok as we discussed, but how about the first one? Thanks for your help.
I'm afraid I still don't understand the issue.
Have you tried to use the Parser
instead?
Yes, i've tried to use the Parser. The following sourceds are the content of Stuff.h and Stuff.java (generated from StuffConfig).
Stuff.h
std::vector<unsigned char> foo();
std::vector<double*> vpd_result;
std::vector<double*> * vpd_result_pointer;
Stuff.java
// Parsed from Stuff.h
// #include <vector>
public static native @Cast("unsigned char*") @StdVector BytePointer foo();
public static native @Cast("double**") @StdVector PointerPointer vpd_result(); public static native void vpd_result(PointerPointer vpd_result);
public static native @Cast("double**") @StdVector PointerPointer vpd_result_pointer(); public static native void vpd_result_pointer(PointerPointer vpd_result_pointer);
I didn't understand why there is no difference between vpd_result & vpd_result_pointer in Stuff.java, although in Stuff.h, they are not the same thing.
The @StdVector
adapter just copies the whole vector and returns the copy. It doesn't matter if the original vector is returned by pointer or by value.
Hi Samuel,
I still couldn't figure out how does it work. I've tried this example this works well.
stuff.h
std::vector<std::string> vd_Indicators;
stuff.java
public native @StdVector DoublePointer vd_Indicators();
public native Struct_Simulation_Results vd_Indicators(@StdVector DoublePointer vd_Indicators);
However if I changed the definition in stuff.h
stuff.h
//std::vector<std::string> vd_Indicators;
std::vector<std::string> * vd_Indicators = new std::vector<std::string>();
It causes immediately a crash in the java virtual machine.
I assume that in this case the Java definition @StdVector DoublePointer vd_Indicators()
could not be used with std::vector<std::string> * vd_Indicators
.
So I don't understand your phrase Samuel. A pointer or a value is really a problem here.
Another example,
stuff.h
std::vector<std::string> * vs_labels = new std::vector<std::string>();
stuff.java
@Name("std::vector<std::string>") public static class StringVector extends Pointer { }
Here I retakes the definition in open_cv.core.
There no problems with the pointer std::vector<std::string> * vs_labels
.
How ever if I use a value instead
stuff.h
//std::vector<std::string> * vs_labels = new std::vector<std::string>();
std::vector<std::string> vs_labels;
then the JVM is crashed as the previous example.
Somes observations here:
You're right that there was some native support missing for vector pointers to work with @StdVector
. It should work with the changes from the latest commit: https://github.com/bytedeco/javacpp/commit/f61ac32ec07bb0c1e0e96e40480ebac40823c6bd
Let me know! Thanks
Hi Samuel,
But it's ok now, by placing a @ByVal before StringVector in the class (struct) that use this StringVector, for ex:
public native @ByVal VectorStringPointer vs_labels();
public native structTimeSeriesResults vs_labels(@ByVal VectorStringPointer vs_labels);
I understand JavaCPP better now. Thanks for your help.
Hi, I have a struct like the one below:
I've tried to use
std:vector<double*>
directly, it works. For example:std:vector<double*> vpd_result;
But the problem appears when I use:I've read this thread, which has the similar problem: https://groups.google.com/forum/#!searchin/javacpp-project/typedef/javacpp-project/YhOOggLfkzc/0i7kp3YqrFoJ
but I really don't understand the code.
How could you map this into javacpp?
Thanks for your help