|
|
|
![]() |
|
|||||||
|
||||||||
![]() |
| Thread Tools | Rate Thread | Display Modes |
|
#1
|
||||
|
||||
|
Native C string (char*) to java String
I'm trying to get the Java ZomB bindings working, and I seem to be having an issue with getting returned C strings (a const char* to be exact). I have this function:
Code:
private static final Function getstringfnc = NativeLibrary.getDefaultInstance().getFunction("ZomBDashboardGetString");
public String GetString(String name)
{
int returnstring = getstringfnc.call1(Pointer.createStringBuffer(name));
return Pointer.NativeUnsafeGetString(Address.fromPrimitive(returnstring));
}
Code:
extern "C"
{
const char* ZomBDashboardGetString(const char* name);
}
Java Source attached, C header and out file are on FIRST Forge (just use the latest build's installer, and its in C:\Program Files\ZomB\Bindings) |
|
#2
|
||||
|
||||
|
Re: Native C string (char*) to java String
I don't see a killer bug, but there is one thing to clean up.
1) Each call to Pointer.createStringBuffer() essentially "mallocs" a new C string buffer, so you typically need to free it after calling the C function (unless the C code stashes the value somewhere to use later). To fix this, create a local Pointer variable, say "ptr", and call ptr.free() after the call out to C. Also, I'm not sure what died, and what the symptoms are. Something on the cRIO or the driver station? And I couldn't find the C code for ZomBDashboardGetString(), etc. Is it in the svn somewhere? Good luck! |
|
#3
|
||||
|
||||
|
Re: Native C string (char*) to java String
Quote:
Code:
zombinstance.Send("taco", joystick.GetY());
Code:
zombinstance.Send("taco", joystick.GetY());
zombinstance.Send("value", zombinstance.GetString("invalue"));
The h file should be in C:\Program files\ZomB\Bindings\ (or Start>Programs>ZomB>Bindings) and the cpp file is compiled into ZomB.out, but you can see it in svn (\releasefiles\bindings\source), but I've attached both |
|
#4
|
|||
|
|||
|
Re: Native C string (char*) to java String
It seems that you may be leaking a fair amount of memory. Remember that in C++ (unlike Java) you can't just new something (like a string or array of char) and then forget about it and expect a garbage collector to clean up after you. You need to be more deliberate about your allocations. Such as:
Code:
char* System451::Communication::Dashboard::ZomBTCPSource::readBytes(int number)
{
char* buf = new char[number+1];
...
Code:
void System451::Communication::Dashboard::ZomBTCPSource::sendreader()
{
...
curvalues[*new string(buf)] = const_cast<const char*>(vbuf);
...
Any time you are done with a heap-allocated ("new"ed) variable, you should delete it. Such as here: Code:
int System451::Communication::Dashboard::ZomBTCPSource::readByte()
{
char r = this->readBytes(1)[0];
...
Code:
char* System451::Communication::Dashboard::ZomBTCPSource::readBytes(int number)
{
...
delete buf2;
...
You are returning a C++ allocated string back to Java and depending on it sticking around. That's a safe assumption I guess if you never delete anything, but you really should be deleting them when they change. The way this is typically done is to allocate a buffer in Java, pass that out to the "GetString" function, and strcpy the value into the Java string. This way Java is in control of the lifetime of that allocated memory. If you are worried about the string length, then you can split the C entry-point into 2 parts and request the length first and then allocate a buffer in Java and then get the string. I wouldn't be surprised if things were dying as a result of some of these memory allocation issues. -Joe |
|
#5
|
||||
|
||||
|
Re: Native C string (char*) to java String
I have been able to get labview to work fine with it, so i'm sure its on the Java side call, since it dies IMMEDIATELY, and I've gotten C++ and LabVIEW to stick around for at least a minute.
|
|
#6
|
|||
|
|||
|
Re: Native C string (char*) to java String
Quote:
Quote:
If the DS still says there is code, then at least part of the JVM is still running a DS thread. Perhaps you are seeing a deadlock between your Java objects. Or maybe a task in C++ is crashing while holding a sync object that one of these calls needs. However, you don't seem to be using the BlockingFunction JNA function object, so if you blocked outside of Java, the whole VM would hang and stop the DS thread in Java. See if you can isolate the issue a bit more. -Joe |
|
#7
|
||||
|
||||
|
Re: Native C string (char*) to java String
Ok, i've narrowed it down a bit, and the crashing is due to Double.parseDouble("") throwing an exception because GetString is always returning "" (empty string)
Code:
public String GetString(String name)
{
Pointer ptr = Pointer.createStringBuffer(name);
int retturn = getstringfnc.call1(ptr);
Address adr = Address.fromPrimitive(retturn);
String str = Pointer.NativeUnsafeGetString(adr);
System.out.println("String:'"+str+"'");
ptr.free();
return str;
}
public double GetDouble(String name)
{
try
{
return Double.parseDouble(GetString(name));
}
catch(Throwable t) { }
return 0;
}
Code:
public void operatorControl() {
getWatchdog().setEnabled(false);
while (isOperatorControl()) {
if (z.CanSend()) {
z.Add("taco", stick.getY());
z.Add("val", z.GetDouble("ival"));
z.Send();
}
Timer.delay(0.01);
}
}
Code:
String:'' String:'' String:'' String:'' String:'' String:'' String:'' String:'' String:'' String:'' String:'' String:'' |
|
#8
|
|||
|
|||
|
Re: Native C string (char*) to java String
Have you ever seen the "NativeUnsafeGetString" actually work?
|
|
#9
|
||||
|
||||
|
Re: Native C string (char*) to java String
No, it just seemed like it should
|
|
#10
|
|||
|
|||
|
Re: Native C string (char*) to java String
I recommend that in both LabVIEW and Java, change the API such that you allocate a string in the client language, pass the pointer out to your API to be populated, then consume it in the client language. This should resolve your problem.
-Joe |
|
#11
|
||||
|
||||
|
Re: Native C string (char*) to java String
changing the C sig to
PHP Code:
PHP Code:
Quote:
|
|
#12
|
||||
|
||||
|
Re: Native C string (char*) to java String
Oh! Duh!
I was initializing it as ZomBDashboard zomB = ZomBDashboard.getInstance(ZomBModes.TCP, "10.4.51.5"); not as ZomBDashboard zomB = ZomBDashboard.getInstance(ZomBModes.AllTCP, "10.4.51.5"); It works now! |
![]() |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Unflatten from String | Patrick Chiang | Programming | 2 | 20-02-2010 09:31 |
| string | Adama | Inventor | 1 | 07-11-2007 14:45 |
| String Theory | Michael Hill | Math and Science | 20 | 02-09-2005 14:11 |
| is string legal? | Jeremy L | Kit & Additional Hardware | 7 | 07-03-2004 16:28 |