-
Notifications
You must be signed in to change notification settings - Fork 588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using @Virtual with method returning @StdString generates function returning dangling reference #374
Comments
Yes, by default it assumes we're passing by reference because that's what is most widely used, but when if we need to pass by value, we can override the cast with something like this: @Virtual public native @Cast({"", "std::string"}) @StdString BytePointer get_property(); BTW, when passing by value @Virtual public native @Cast({"", "std::string"}) @StdString String get_property(); |
But why is explicit cast is neccessary here? If you pass |
We're not doing conversions, we're implementing a function. |
You're talking about other use cases? There are a lot of functions with |
Yeah, you are right. BTW, that NativeClass Java class is what Parser generated for me. Meaning that it knew that get_property() returns by value but didn't add |
Also, how does one use this function: virtual std::string wtf(std::string str) { return str; } With following Java code @Virtual native @Cast({"", "std::string"}) @StdString String wtf(@Cast({"", "std::string"}) @StdString String str); I get ambiguous call error:
|
The idea with cast operators is that we can have the compiler make some guesses. We can't do that with normal functions, so it's not clear that it's better...
Ah yes, that's right, the Parser doesn't have any information about whether any given annotation is an adapter or not. It only outputs a cast like that when it encounters template types for which no information was provided, in which case it knows that we're probably going to have an adapter for those, but it can't guess that for normal types like |
Yeah, the problem in that case is that the adapter doesn't return |
I see two options:
class StringAdapter {
/// ...
const char* toPointer();
char* toPointer();
const unsigned short* toPointer();
unsigned short* toPointer();
std::basic_string<T>& toContainer();
std::basic_string<T>* toContainer();
/// ...
}
class VectorAdapter {
/// ...
const P* toPointer();
P* toPointer();
std::vector<T>& toContainer();
std::vector<T>* toContainer();
/// ... As far as I understand, |
We can't have 2 functions with the same signature, that won't work.
|
Oh lol, I don't know how I missed that. template<typename T = char> class StringAdapter {
public:
class ToContainer {
public:
ToContainer(const T* ptr, typename std::basic_string<T>::size_type size, void* owner);
ToContainer(const unsigned short* ptr, typename std::basic_string<T>::size_type size, void* owner);
// ...
operator std::string&();
operator std::string*();
// ...
};
class ToPointer {
public:
ToPointer(const std::basic_string<T>& str);
ToPointer(std::basic_string<T>& str);
ToPointer(std::basic_string<T>* str);
// ...
operator const T*();
operator T*();
operator const unsigned short*();
operator unsigned short*();
// ...
};
}; This way if we want to pass On the slightly unrelated note: I think that it would be good idea to use static_cast for adapter conversions. It will catch some cases when conversions are not possible at compile time. Using C-style cast will do reinterpet_cast instead of proper conversion in these cases resulting in undefined behaviour. For example, it is possible when casting to references. |
Yes, that solves some issues, but at the cost of added complexity, and it doesn't change anything for cases like yours with BTW, you could create your own custom adapter that converts only to
Ideally, yes, but that also adds complexity because |
For example, for this Java code:
Following C++ class is generated:
Where JavaCPP_NativeLibrary_0003a_0003aNativeClass::get_property() is:
JavaCPP_NativeLibrary_0003a_0003aNativeClass::get_property() should return by value, not reference. It also means that generated override actually overrides nothing, since NativeLibrary::NativeClass::get_property() returns by value.
I suspect that it is caused by StdString.java having
@Cast({"std::basic_string", "&"})
annotation, but I'm not sure why it is there.The text was updated successfully, but these errors were encountered: