Yes, for obscure historical reasons, the `std::string` class does not
support implicit conversion to `const char*`, the type required by
Java's `NewStringUTF()`. We need to call `std::string.c_str()` manually,
which is quite a bother. For that reason I added a hack such that it
gets returned that way when declaring `@ByRef String` on the Java side,
i.e. for your function:
public static native @ByRef String capitalize(String str);
should work as expected.
Samuel
On 2011-10-01 08:31, CarlH wrote:
> I'm trying to wrap a library function that returns a "std::string" but
> the JavaCPP JNI code that is generated tries to assign the return
> value to a "const char*". Not sure what I'm doing wrong...
>
> Here's the function declaration from header file:
> --------------------------------------------------------------
> std::string capitalize( const std::string& str );
How about better java attribute names?
Instead of @byref String add new attribute @ctype.
It will do the best conversion from the java parameter (or return type) and this c type, or choke on error if it can't.
In the case of String, I had it done before coming up with Adapter.
Passing String objects by reference to Java makes no sense because its
memory can't be mapped to native memory, and since this is only a
problem with C++, which has pass-by-reference, unlike C, which does not,
I thought it would be a good use of "@ByRef String" to mean "C++ String" ;)
Samuel
On 2011-10-01 18:40, Dror Tirosh wrote:
> How about better java attribute names?
> Instead of @byref String add new attribute @ctype.
> It will do the best conversion from the java parameter (or return type)
> and this c type, or choke on error if it can't.
>
> On Oct 1, 2011 3:49 AM, "Samuel Audet" <samuel...@gmail.com
Adapter works, but doesn't give access to the java type: if i define a String parameter with @Adapter it will pass the char* pointer, not the jstring. Thus i can't write my own adapter.
Right, I designed JavaCPP so we did not have to muck around with JNI.. I
could add a @Raw annotation or something for people who really want to
do that I guess, but I really don't see the point. What are you trying
to do here anyway? It's like trying to use a C++ object from assembly
language, a nightmare. Got better things to do...
Samuel
The only safe, practical, and efficient way of doing that in Java is
with NIO direct buffers. It's also possible to do it efficiently *or*
safely with arrays, but not efficiently *and* safely. But it's /not/
possible to do it efficiently with String, StringBuilder, StringBuffer
or anything else related with strings.
BTW, copying something of 1 kB isn't "large", so do not worry about
copying stuff that is so small. It all fits in L1 cache
> 2. return multiple strings. so that I can write a c++ function like:
> void getinfo( string& ret_name, string& ret_lastname, string&
> ret_title )
> and wrap into with the java method:
> void GetInfo( StringBuilder ret_name, StringBuilder ret_lastname,
> StringBuilder ret_title );
It's possible to do have
void getInto(char *ret_name, char *ret_lastname, char *ret_title)
that maps directly to
void getInfo(ByteBuffer ret_name, ByteBuffer ret_lastname,
ByteBuffer ret_title)
If you really really want to use std::string, then it's possible to
make an Adapter for that yes, which would look like this:
void getInfo(@Adapter("StringAdapter") BytePointer ret_name,
@Adapter("StringAdapter") BytePointer ret_lastname,
@Adapter("StringAdapter") BytePointer ret_title)
> (in some cases this could be avoided if we had a simple callback from c++ to
> java...)
JavaCPP does support callback functions, but it's inefficient and
hackish to call into the JVM from native code, so I would not
recommend it
Samuel