Hi Jerven,
so I experimented a bit - this is my result:
I replaced the contents of odgi_load_graph with a plain printf and
could reproduce your findings, but then I continued and had a look at
the parameters and return type and noticed, the return type.
It is:
ograph_t
which is defined as:
typedef std::shared_ptr<graph_t> ograph_t;
This is not a plain C type and indeed, once I replaced that with a void
or void* behavior became sane. I don't know what a std::schard_ptr is
really, but I suspect its a structure and because of this the stack
layout libffi created was not what the function invocation expected.
You need to get hold of the raw pointer and pass that.
For the version I suspect, that you see the C++ runtime cleaning up
after itself. I don't know when C++ makes a copy of the value and frees
it and indeed this might become a problem. I have to working versions:
const char* odgi_c_version(){
// Version::VERSION is const, so passing the pointer to the C string should
// be save. Of course it must not be freeed then!
printf("Version: %s\n", Version::VERSION.c_str());
fflush(stdout);
return Version::VERSION.c_str();
}
As commented this relies on noone modifying Version::VERSION, once a
modification is done, the result from ::c_str becomes invalid (see
documentation of string::c_str).
That gives me:
Version: 8e221f3
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.13
sec <<< FAILURE!
testVersionNotNull(swiss.sib.swissprot.odgi4j.Odgi4jTest) Time
elapsed: 0.015 sec <<< FAILURE!
java.lang.AssertionError: 8e221f3
at org.junit.Assert.fail(Assert.java:89)
While the output looks like gibberish, IMHO it is sane:
- Native and Java agree on the value (first line comes from native,
the AssertionError holds the Java value)
- it matches the short hash of the checked out revision I build odgi
from
An alternative version to the above would be:
const char* odgi_c_version(){
auto version = odgi_version();
char * cstr = (char*) malloc(version.length()+1);
std::strcpy (cstr, version.c_str());
printf("Version: %s\n", cstr);
fflush(stdout);
return cstr;
}
Which gives me the same result as the first variant. However to not
leak memory the returned value must be freed by the caller:
Native.free(Pointer.nativeValue(versionPointer));
TL;DR: This works, although the asserts are wrong.
Hope that helped
Matthias