No luck getting C Struct from external library into Xojo structure

We have a C function that returns a relatively simple struct of 4 Int32 values:

typedef struct CVCRect {
    int x, y, width, height;
} CVCRect;

CVCRect CVCRectVectorAt(CVCRectVector rectVector, size_t index)
{
   cv::Rect rect = ConstCVCRectVectorRef(rectVector).at(index);
   return CVCRectCreate(rect.x, rect.y, rect.width, rect.height);
}

CVCRect CVCRectCreate(int x, int y, int width, int height)
{
   try {
      cv::Rect *rect = new cv::Rect(x, y, width, height);
      return (CVCRect)rect;
   } catch (...) { }
   return NULL;
}

When we try to get the returned CVCRect Struct from CVCRectVectorAt() into Xojo, it simply crashes.

What is the best way to get the result of the above function into the following Xojo structure?

CVCreateRect appears to be returning a pointer to the structure, so declare the return type as Ptr. Then you can extract the struct from the ptr.

Declare CVCreateRect lib somelib (x as integer, y as integer, width as integer, height as integer) as Ptr
dim p as ptr = CVCreateRect(x, y, w, h)
dim r as CVCRect = p.CVCRect(0)

Ptr automatically knows about Structures.

We’re not calling CVCRectCreate in this instance. I only included that snippet to show what’s happening behind the scenes. We’re calling CVCRectVectorAt, which calls the wrapped C++ API function cv::Rect, which creates a new Rect struct (in C) to return to Xojo.

In any case, I’ve modified my Xojo code to take the result of CVCRectVectorAt as a ptr, but it still crashes:

//create a handle to a rectvector
var h as ptr = openCV.CVCRectVector.CVCRectVectorCreate

//build some rects 
var rect as CVCRect
rect.x = 23
rect.y = 110
rect.width = 50
rect.height = 50

var rect2 as CVCRect
rect2.x = 42
rect2.y = 111
rect2.width = 52
rect2.height = 53

//Add the rects to the rectvector
openCV.CVCRectVector.CVCRectVectorPushBack( h, rect)
openCV.CVCRectVector.CVCRectVectorPushBack( h, rect2)

//verify there's something there (there should be two items; there are)
var rSize as UInteger = opencv.CVCRectVector.CVCRectVectorSize( h )

//retrieve a rect from the rectvector and stuff it into a copy
var rectCopy as CVCRect
var vect as ptr = opencv.CVCRectVector.CVCRectVectorAt( h, 1 )
rectCopy = vect.CVCRect(0)

break

And this crashes.

Well CVCRectorAt() calls CVCRectCreate() which returns a CVCRect structure or NULL. You say Xojo crashes, is there an unhandled exception, if so what does it return ?

I wonder if it’s a case of little endian vs big endian. See What Is Little-Endian And Big-Endian Byte Ordering? | Engineering Education (EngEd) Program | Section

Oh, and since CVCRectVectorAt can return NULL, that will break everything if a return value of NULL is not trapped.

trapped on the xojo or C-side?

On the Xojo side. If you try to do something with the (pointer to a) structure that is set to NULL, you will get an exception. The best way to do this is to check if the value is NULL, if so don’t process the structure and handle this error condition. Since I don’t know the specific of your app, I can’t suggest anything more specific.

So maybe I’m not understanding how to catch that.

var vect as ptr = opencv.CVCRectVector.CVCRectVectorAt( h, 1 )

if vect <> nil then
  rectCopy = vect.CVCRect(0)
else
  break
end if

When I run this, it crashes at the first line, before I can test it if it’s nil. The app also crashes when I wrap the call to CVCRectVectorAt in a try/catch:

Try
  var vect as ptr = opencv.CVCRectVector.CVCRectVectorAt( h, 1 )
  rectCopy = vect.CVCRect(0)
  
Catch e As RunTimeException
  Raise e 
  MessageBox(e.Message)
End Try

BTW - Console (Mac) says:

Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x000000000000002a
Exception Note: EXC_CORPSE_NOTIFY

Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [98106]

What is the Xojo declare for CVCRectVectorAt? What are the parameter types?

Private Declare Function CVCRectVectorAt Lib libName (h as Ptr, index as integer) As Ptr

Perhaps peeking at the memory of the structure will be enlightening?

var vect as ptr = opencv.CVCRectVector.CVCRectVectorAt( h, 1 )
var mb As MemoryBlock = vect

So the problem is that it blows up on the call to CVCRectVector. We never get to the point where we can put it in a memory lock to look at it. Same issue as the try/catch not working, I think.

What does your declare look like for CVCRectVectorPushBack?

Private Declare Sub CVCRectVectorPushBack Lib libName (h as Ptr, rect as cvcRect)

Aha. I think the issue was that the rect isn’t passed to CVCRectVectorPushBack byref. Once I did that I started getting a valid result.

Thanks for helping to puzzle through this!