Mapping char** in JNI - java-native-interface

My native function accepts char ** as argument . Will anybody help me how should I pass it using JNI.
my native function protocol - long processInput(const char* str1 , char ** output);
Thanks

You cannot really do this directly, but you can't easily call an arbitrary function name with JNI either - so you'll need a simple native wrapper method. Start with the hello-jni sample from the Android ndk distribution samples/ directory, build it as is to make sure everything works, then change it to be something like this:
long processInput(const char* str1 , char ** output);
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
//return (*env)->NewStringUTF(env, "Hello from JNI !");
char *outputstr;
processInput("some input", &outputstr);
return (*env)->NewStringUTF(env, outputstr);
}
You will probably also want to add error checking, maybe get the input string from jni, etc.

This is not a complete answer (yet) but it is too long for a comment.
Start by writing a native function declaration in Java such that it fits into Java naturally. Maybe one of these would be appropriate:
static native String processInput(String input);
static native byte[] processInput(byte[] input);
Then, in order to wrap the function, you have to know:
The meanings of the return value and each parameter.
If the char parameters represent strings, what are the
character set,
encoding and
length/terminator protocol.
What memory is the caller expected to allocate and/or free?
The callee?
If the return value is some special value, does that mean output is not relevant, in which case should the wrapper throw a Java exception or return a null string, null array or zero-length array?
Java uses Unicode for strings. What should happen if characters can't be mapped to the character set used by the function?

Related

Convert char* into String

I am using ESP8266 Wifi chip with the SMING framework which uses C++. I have a tcpServer function which receives data from a TCP port. I would like to convert the incoming char *data into String data type. This is what I did.
bool tcpServerClientReceive(TcpClient& client, char *data, int size)
{
String rx_data;
rx_data = String(data);
Serial.printf("rx_data=%s\r",rx_data);
}
The contents of rx_data is rubbish. What is wrong with the code? How to make rx_data into a proper string?
Why what you are doing is wrong:
A C style string is an array of char where the last element is a 0 Byte. This is how functions now where the string ends. They scan the next character until they find this zero byte. A C++ string is a class which can hold additional data.
For instance to get the length of a string one might choose to store the length of the stirng in a member of the class and update it everytime the string is modified. While this means additional work if the string is modified it makes the call t length trivial and fast, since it simply returns the stored value.
For C Strings on the other hand length has to loop over the array and count the number of characters until it finds the null byte. thus the runime of strlen depends on the lengh of the string.
The solution:
As pointed out above you have to print it correctly, try either:
#include <iostream>
...
std::cout << "rx_data=" << rx_data << std::endl;
or if you insist on printf (why use c++ then?) you can use either string::c_str(), or (since C++11, before the reutrned array might not be null terminated) string::data(): your code would become:
Serial.printf("rx_data=%s\r",rx_data.c_str());
I would suggest you have a look at std::string to get an idea of the details. In fact if you have the time a good book could help explaining a lot of important concepts, including containers, like std::string or std::vector. Don't assume that because you know C you know how to write C++.

Get C++ wchar_t into Flash, via Lua

I am currently working on an application in C++, that ties into Lua, that ties into Flash (in that order). My goal at the moment is getting wchar_ts from C++ into Flash, via Lua. I would love any insights as to how I can accomplish this!
If any other information is required, please ask and I'll do my best to provide it
What I have tried
It's my understanding that Lua is not a fan of Unicode, but it should still be able to receive the string of bytes from my C++ application. I imagine there must be a way to then pass those bytes over to Flash to then render out my intended Unicode. So what I've done so far:
C++:
//an example wchar_t*
const wchar_t *text = L"Test!";
//this function pushes a char* to my Lua code
lua.PushString((char*)text); //directly casting text to a char*... D:
Lua:
theString = FunctionThatGetsWCharFromCpp();
flash.ShowString(theString);
Flash:
function ShowString(theString:String)
{
myTextField.text = theString;
}
Now the outcome here is that myTextField only shows "T". This made sense to me. The cast from wchar_t to char would end up padding out the chars with some zeros, especially since "T" doesn't really utilize both bytes of a wchar_t. A quick look at the documentation yields:
lua_pushstring
The string cannot contain embedded zeros; it is assumed to end at the first zero.
So I ran a little test:
C++:
//prefixing with a Japanese character
//which will use both bytes of the wchar_t
const wchar_t *text = L"たTest!";
The Flash textbox now reads: "_0T", 3 characters. Makes total sense, the 2 bytes of the Japanese character + T, then termination.
I understand what is going on, but I am still completely unsure of how to tackle this problem. And I'm really unsure of what to search for. Is there a specific Lua function I can use to pass a wad of bytes over to Lua from C++ (I've read somewhere that lua_pushlstring is often used for this, but that also terminates at first zero)? Is there a Flash datatype that will accept these bytes, then I'll need to do some sort of conversion to get them into a readable, multibyte string? or is this just really not possible?
Note:
I'm not too familiar with Unicode and code pages and whatnot, so I'm not too sure if there'll also be a step where I'll need to specify the correct encoding in Flash so that I can get the correct output - but I'm happy to cross that bridge when I get there, but if anyone has any insight here too, that would be great!
I don't know if this will work, but I'd recommend trying to use UTF-8. A string encoded in UTF-8 doesn't have any embedded zeros in it, so Lua should be able handle it, and Flash ought to also be able to handle it, depending on how exactly the languages interface.
Here's one way to convert a wide-character string to UTF-8 using setlocale(3) wcstombs(3):
// Error checking omitted for expository purposes
// Call this once at program startup. If you'd rather not change the locale,
// you can instead write your own conversion routine (but beware of UTF-16
// surrogate pairs if you do)
setlocale(LC_ALL, "en_US.UTF-8");
// Do this for each string you want to convert
const wchar_t *wideString = L"たTest!";
size_t len = wcslen(wideString);
size_t maxUtf8len = 4 * len + 1; // Each wchar_t encodes to a max of 4 bytes
char *utf8String = new char[maxUtf8len];
wcstombs(utf8String, wideString, maxUtf8len);
...
// Do stuff with utf8string
...
delete [] utf8String;
If you're on Windows, you can instead use the WideCharToMultiByte function with the CP_UTF8 code page to do the conversion, since I don't believe that the Visual Studio C runtime supports UTF-8 locales:
// Error checking omitted for expository purposes
const wchar_t *wideString = L"たTest!";
size_t len = wcslen(wideString);
size_t maxUtf8len = 4 * len + 1; // Each wchar_t encodes to a max of 4 bytes
char *utf8String = new char[maxUtf8len];
WideCharToMultiByte(CP_UTF8, 0, wideString, len + 1, utf8String, maxUtf8len, NULL, NULL);
...
// Do stuff with utf8string
...
delete [] utf8String;

How to invoke an exported function from DLL written in C/C++ which return type is char* or string?

We designed C/C++ DLL just like this:
WIN32_DLL_EXPORT int FnRetInt(int i)
{
....
return 32 ;
}
WIN32_DLL_EXPORT char* FnRetString()
{
return "THIS IS A TEST STRING" ;
}
when we invoke these two functions in Go by using syscall:
hd:=syscall.NewLazyDLL(dll_path)
proc:=hd.NewProc(dll_func_name)
ret:=proc.Call()
we found:
FnRetInt worked ok, but FnRetString didn't. proc.Call return type is uintptr, how can we change it to the type we wanted (for exsample: char* or string)?
A uintptr is a Go type that represents a pointer. You can use the unsafe package and convert it to unsafe.Pointer, and then you can convert an unsafe.Pointer into any Go pointer type. So you could do something like
str := (*uint8)(unsafe.Pointer(ret))
to get a *uint8 back.
Look at syscall.Getwd windows implementation http://code.google.com/p/go/source/browse/src/pkg/syscall/syscall_windows.go#323. It is different from your problem:
it passes buffer to the dll, instead of receiving it from dll;
the data is uint16s (Microsoft WCHARs), instead of uint8s;
GetCurrentDirectory tells us how long resulting string is going to be, while your example, probably, expects you to search for 0 at the end;
But should give you enough clues.
Alex

Integration of C++ in C infrastructure

C++ is real handy in most projects, but sometimes you just have to integrate with existing C style functions.
How do you do that in a neat way, especially, if you work with strings?
I had an idea that I could use construct like this:
std::string buffer;
buffer.resize(1024);
GetBackCStyleString(&buffer[0], 1024);
But this causes problems with string length, as it returns the resized length. Is there a better way to integrate C functions in C++ code?
That's a good solution. If you want the size to be accurate, call resize again after the function returns and you can calculate the actual length.
e.g.
buffer.resize(GetBackCStyleString(&buffer[0], buffer.size());
if the function returns the length, or
GetBackCStyleString(&buffer[0], buffer.size()
buffer.resize(strlen(&buffer[0]));
otherwise.
buffer.c_str() if function takes const char* or const_cast<char*>(buffer.c_str()) if function takes char*. In the latter case be cautious
Create a plain char somebuf[somesize]; buffer and let the C function write into that.
Then create a std::string from it using std::string buffer(somebuf).
If the function just wants a const char * (i.e. an "input" parameter), simply pass yourStdString.c_str() to it.

How to convert AS3 ByteArray into wchar_t const* filename? (Adobe Alchemy)

How to convert AS3 ByteArray into wchar_t const* filename?
So in my C code I have a function waiting for a file with void fun (wchar_t const* filename) how to send to that function my ByteArray? (Or, how should I re-write my function?)
A four month old question. Better late than never?
To convert a ByteArray to a String in AS3, there are two ways depending on how the String was stored. Firstly, if you use writeUTF it will write an unsigned short representing the String's length first, then write out the string data. The string is easiest to recover this way. Here's how it's done in AS3:
byteArray.position = 0;
var str:String = byteArray.readUTF();
Alternatively, toString also works in this case. The second way to store is with writeUTFBytes. This won't write the length to the beginning, so you'll need to track it independantly somehow. It sounds like you want the entire ByteArray to be a single String, so you can use the ByteArray's length.
byteArray.position = 0;
var str:String = byteArray.readUTFBytes(byteArray.length);
Since you want to do this with Alchemy, you just need to convert the above code. Here's a conversion of the second example:
std::string batostr(AS3_Val byteArray) {
AS3_SetS(byteArray, "position", AS3_Int(0));
return AS3_StringValue(AS3_CallS("readUTFBytes", byteArray,
AS3_Array("AS3ValType", AS3_GetS(byteArray, "length")) ));
}
This has a ridiculous amount of memory leaks, of course, since I'm not calling AS3_Release anywhere. I use a RAII wrapper for AS3_Val in my own code... for the sake of my sanity. As should you.
Anyway, the std::string my function returns will be UTF-8 multibyte. Any standard C++ technique for converting to wide characters should work from here. (search the site for endless reposts) I suggest leaving it is as it, though. I can't think of any advantage to using wide characters on this platform.