MemoryBlock issue with libffi

I’m using libffi in one of my projects. It enables you to call functions in C libraries without having to declare each of these functions as external functions in Xojo.

Everything works fine with one exception: I’m not able to call functions which return non-scalar values (Ptr, CString, etc.).

So this works fine:

Function TestInt32(i1 As Int32, i2 As Int32) As Int32 Return i1 + i1 End Function

But this function returning a pointer fails:

[code]Function TestPtr(p1 As Ptr, p2 As Ptr) As Ptr
Dim mb1 As MemoryBlock = p1
Dim s1 As String = mb1.CString(0)

Dim mb2 As MemoryBlock = p2
Dim s2 As String = mb2.CString(0)

Dim length As Integer = s1.Len + s2.Len + 1

Dim mb3 As New MemoryBlock(length)
mb3.CString(0) = s1
mb3.CString(s1.Len) = s2

Return mb3
End Function[/code]
The return value after the last line Return mb3 is correct, but the ffi_call receives garbage.
When I test the function by a direct call (circumventing ffi_call) it works fine.

If I first copy the result with memcpy to a newly allocated memory chunk, everything works fine:

[code]Function TestPtr(p1 As Ptr, p2 As Ptr) As Ptr
Dim mb1 As MemoryBlock = p1
Dim s1 As String = mb1.CString(0)

Dim mb2 As MemoryBlock = p2
Dim s2 As String = mb2.CString(0)

Dim length As Integer = s1.Len + s2.Len + 1

Dim mb3 As New MemoryBlock(length)
mb3.CString(0) = s1
mb3.CString(s1.Len) = s2

Const libc = “/usr/lib/libSystem.B.dylib”
Declare Function malloc Lib libc (size As Int32) As Ptr
Declare Function memcpy Lib libc (destination As Ptr, source As Ptr, num As Int32) As Ptr

Dim p As Ptr = malloc(length)
Call memcpy(p, mb3, length)
Return p
End Function[/code]

Why is this better than declares? You still need to provide type information, the function name, and the library…?

It’s not better than declares. But I don’t want to write 280 declares, when I can have the same result with less than 200 lines of code. The only thing, which I haven’t figured out yet, is the above issue.

Coud it be that mb3 in the failing routine is being cleaned up by Xojo when ther function exits as the return value is only a pointer and not the memoryblock ?

Whereas in the working code the memory being pointed to is got via malloc and so is never being freed.

[quote=77471:@Eli Ott]But this function returning a pointer fails:

Function TestPtr(p1 As Ptr, p2 As Ptr) As Ptr
Dim mb1 As MemoryBlock = p1
Dim s1 As String = mb1.CString(0)

Dim mb2 As MemoryBlock = p2
Dim s2 As String = mb2.CString(0)

Dim length As Integer = s1.Len + s2.Len + 1

Dim mb3 As New MemoryBlock(length)
mb3.CString(0) = s1
mb3.CString(s1.Len) = s2

Return mb3
End Function

The return value after the last line Return mb3 is correct, but the ffi_call receives garbage.[/quote]

In the Xojo’s Ref documentation for Memoryblock says following: A MemoryBlock can be passed in place of a Ptr when used in a Declare call.

just out of curiosity. What will happen if you returned a ptr instead of mb3.

Dim p4 As Ptr
p4 = mb3  // A Ptr to the MemoryBlock 
Return p4

That’s what I suspected too.

The same.

Actually it is not really a problem (took me some time to realize that), since it works perfectly with the library I want to use it for.

So it must be something with the memory handling of the Xojo framework when returning a MemoryBlock and the internals of how libffi calls that function.

Thanks for your help!

[quote=77576:@John Hansen]In the Xojo’s Ref documentation for Memoryblock says following: A MemoryBlock can be passed in place of a Ptr when used in a Declare call.
[/quote]
What that means is that Xojo will auto convert the memory block in the call to a declare.