Returning allocated structure from C
BlitzMax Forums/BlitzMax Programming/Returning allocated structure from C
| ||
I'm trying to return a structure (created in C), back to BM. The C routine is thus : struct __HEADER *Create_Header(void) { struct __HEADER *temp; if ((temp=(struct __HEADER *) calloc(1,sizeof(struct __HEADER)))!=NULL) { temp->header=LINKLIST_HEADER; } return (temp); } and the BM code is : Import "/Users/nicholaskingsley/LinkList/LinkList.c" Extern Type LinkListNode Field header:Int Field dataSize:Int Field data:Byte Ptr Field prevNode:LinkListNode Ptr Field nextNode:LinkListNode Ptr EndType Type LinkListHeader Field header:Int Field numNodes:Int Field firstNode:LinkListNode Ptr Field lastNode:LinkListNode Ptr EndType Function Create_Header:LinkListHeader() 'Function Diag:Byte(header:LinkListHeader,fileName$) EndExtern Local header:LinkListHeader header=Create_Header() Print "Returned Header header :" Print header.header The C function is being called no problem, memory is being allocated and the header code is being stored. Unfortunately the value in header.header in BM is 0, which must mean a pointer to the stucture isn't being returned for some reason. |
| ||
Ok. The problem is that you are creating a C struct and trying to assign it to a BlitzMax object. A BlitzMax object is not a C struct - it has an object pointer and a virtual function table much like a C++ struct/class can have. So, what you need to do is to first make your structure a C++ struct and force it to have a vtable pointer by giving it a virtual destructor. This also means renaming your .c file to .cpp firstly so that is is compiled with the C++ compiler. Then you need to define your struct like so :- struct __HEADER { virtual ~__HEADER() {}; // This is the important bit int header; // etc.. }; extern "C" { struct __HEADER *Create_Header(void) { struct __HEADER *temp; if ((temp=(struct __HEADER *) calloc(1,sizeof(struct __HEADER)))!=NULL) { temp->header=195; // test value } return (temp); } } Note that the function definition is now wrapped with extern "C". Now you should be able to import your new .cpp file, call Create_Header and observe that the header field contains the test value 195. Remember you can't expect BM to garbage collect this object - you'll need another function in your .cpp file to destroy it. |
| ||
Also - instead of using calloc() to allocate the structure - you should use the C++ new operator... ie. temp = new __HEADER; if( temp ) { // etc... } Your Delete_Header() function should look something like this :- void Delete_Header( __HEADER *header ) { delete header; } This will call the destructor properly if you do end up putting any code in there. The destructor is the function which begins with a ~ incase you don't know C++ and is called whenever a C++ object goes out of scope or is destroyed. Good luck. |
| ||
BlitzMax object is not a C struct - it has an object pointer and a virtual function table much like a C++ struct/class can have. That's not true for types declared inside an extern block. When BlitzMax was first born these did use to associate directly with C structs, unfortunately on win32 I think they got broken when the com IUnknown interface feature was added. Easiest solution I think is to add a dummy int to the beginning of your C struct declaration (but not your blitzmax extern type definition). |
| ||
To use external C Structs, don't forget that a memory allocated in C is a Byte Ptr, it is not an Int. so assigning Byte Ptr to int will in most cases just be completely wrong. (this is only possible with BM own objects which have a handlefromobject and objectfromhandle functionality) |
| ||
Thanks for that - it works well now. |
| ||
"That's not true for types declared inside an extern block." - ah, I didn't know that. I was half asleep when making his example work and something did strike me a little odd at the time, I didn't expect it to work by adding a single 4 byte param into the struct (the vtable ptr effectively) - now it makes sense. Can we please have some documentation update regarding extern and c/c++ struct/class interfacing - would be nice if this stuff was openly documented. |