String to UnsafePointer<AnsiChar>

I have code that calls JNI functions from both a Silver/Island DLL and a Silver/Cocoa shared library. One of my functions receives a String and needs to pass it as an UnsafePointer to a JNI function:

In the Silver/Cocoa project I simply call someString.UTF8String and all is good. I haven’t figured out the equivalent call in the Silver/Island project. Am I missing something obvious?

Regards,

Benoît

You can use Elements RTL’s cross-platform Encoding class, Encoding.UTF8.GetBytes(string). Or the lower-level Island RTL’s TextConvert.StringToUTF8(string) to get a byte array. you’ll have to padd a #0 char, and then you can pass that as C-compatible char*.

Thank you for the response, Marc.

Both of these provide me with a UInt8[], which is the same thing that would get returned by String.ToByteArray() - how would I get from the UInt8[] to the UnsafePointer?

Hmm, good question. What’s the “address of” operator in Swift? &? if so

let array = Encoding.UTF8.GetBytes("Hello\0") // don't forget the zero
let pointer = &array

should work, and compiles for me.

I tried this already. I admit I haven’t played around with UnsafePointer that much over the years though:

	init(env: UnsafePointer<JNIEnv!>, className: String) {
#ifdef TOFFEE
		_objClass = (*(*env)).FindClass(env, className.UTF8String)
#else
		let array = Encoding.UTF8.GetBytes(className)
		_objClass = (*(*env)).FindClass(env, &array)
#endif
		_objectValue = nil
	}

Error on line 6: Parameter 2 should be “UnsafePointer<RemObjects.Oxygene.System.AnsiChar>”

I would suggest to write a small xml-comment over that function, that one can immediately see, that he needs to add the “0\”, would surely save a lot of threads here I guess :grin: :grin:

There’s also the more convenient:
className.ToAnsiChars(true) which returns an array of ansi char and should be asignment compatbile with ansichar*

1 Like

Thank you Carlo, this is exactly what I was looking for (somehow it escaped me during my search).

Cheers,

-Benoît

1 Like

Strangely, on Windows with Water 2267 I had to change:

myString.ToAnsiChars()

to:

myString.ToString().ToAnsiChars()

This is Silver code in a shared project which gets compiled as an Island (Windows) DLL or as a macOS dylib.

Curious. how is myString defined? can you give me a complete testcase?

It’s defined as a String. If I click it in Water it says it’s an Object.

Here’s a minimalistic test solution. It doesn’t do anything but you may observe this behaviour if you open it in Water and look at the SharedProject code.

StringIssue2.zip (7.4 KB)

Hmm, the code looks rather empty (and compiles clean here):

public class SomeClass {

	public func someFunc(value: String) {
	}

}

It compiles but String shouldn’t be seen as an Object, I believe. I should have put in the body of that function but just try and access value.ToAnsiChars() and you’ll see there’s something amiss.

The problem is you’re using Elements RTL, so your String is an Elements RTL String, not a platform string. even though thats a mapped type, the mapping hides the platform-speciifc APIs and only the cross-platform members defined in Elements RTL String are accessible. You must cast it to RemObjects.Elements.System.String or PlatformString to access platform-speiifc members — which isToAnsiChars is.

This didn’t; change recently though, this has always been the case.

Thanks for clearing this up. I was confused because if I try to edit this using Fire on macOS, it didn’t complain when ‘building’ or edition the Windows DLL project (not that I expect to build binaries for Windows on the Mac, mind you).

strange. it fails for me in Fire the same way. and fwiw, yeah, you can build Island/Windows apps on the Mac just fine. you can even debug them via SSH, if you like :wink: