Custom Annotation for std::string by-value

25 views
Skip to first unread message

Davidson, Josh

unread,
Nov 30, 2021, 3:18:28 PM11/30/21
to javacpp...@googlegroups.com
I’m grappling with something similar to what was asked here: https://groups.google.com/g/javacpp-project/c/Ln10TNF4Now/m/Noj4WseBBAAJ

I am trying to bind some APIs that predominantly pass and return string by-value instead of as reference types. For APIs that pass and return by reference, using something like:

infoMap.put(new Info("std::string").annotations("@StdString").valueTypes("String").pointerTypes("BytePointer"));

works fine. However, the @StdString annotation doesn’t work when for pass and return by value as the generated JNI code will have mismatched signatures. I tried to create a custom annotation that resembles:
@Documented @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER})
@Cast({"std::basic_string"}) @Adapter("StringAdapter")
public @interface ValueString {
String value() default "char";
}

However, this ends up generating calls in the JNI that resemble:
radapter(ptr->myMethod((std::basic_string< char >)adapter0)

Using the StdString annotation, the calls (and cast) resemble:
radapter(ptr->myMethod((std::basic_string< char >&)adapter0)

Without the added reference, the function call operator isn’t invoked, which leads to a constructor ambiguity:
error: call of overloaded ‘basic_string(StringAdapter<char>&)’ is ambiguous
<snip /> radapter(ptr->allocateConfig((std::basic_string< char >)adapter0));
^~~~~~~~
In file included from /usr/include/c++/8/string:52,
from /usr/include/c++/8/stdexcept:39,
from /usr/include/c++/8/array:39,
from /usr/include/c++/8/tuple:39,
from /usr/include/c++/8/bits/unique_ptr.h:37,
from /usr/include/c++/8/memory:80,
from < snip />
/usr/include/c++/8/bits/basic_string.h:518:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
^~~~~~~~~~~~
/usr/include/c++/8/bits/basic_string.h:441:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
basic_string(const basic_string& __str)



Is there another way I can get this to work with the parser without having to manually override “javaText” for each method that passes and returns strings by-value?

Josh

Samuel Audet

unread,
Dec 1, 2021, 6:42:12 AM12/1/21
to javacpp...@googlegroups.com, Davidson, Josh
It's possible to add those @Cast to Info.annotations, or separately in
Info.valueTypes and pointerTypes because they are probably going to be
different. Something like this should work in your case:

infoMap.put(new
Info("std::string").annotations("@StdString").valueTypes("@Cast({\"const
char*\", \"std::string\"}) String").pointerTypes("@Cast({\"char*\",
\"std::string*\"}) BytePointer"));

Samuel
Reply all
Reply to author
Forward
0 new messages