locked
Calling C function that returning pointer to buffer RRS feed

  • Question

  • Hello,

    I have C++/CLI library that is called from Objective-C (ObjC) code. The ObjC code provides a callback pointer to a function declared somewhat like:

    void* invoke_send_message(void* obj, const void* bytes, int* length);

    The function is called from CLI (managed) code and is provided with arguments that are setup within the code. All the time it has not have to return a value, everything works fine.

    However, the callback has to return a pointer to a memory buffer that it allocates. (The length parameter is updated with the length of the returned buffer).

    An attempt to access any element of the returned buffer (by index like ptr[i]) results in AccessViolationException.

    I understand why it is happening (a buffer is allocated on CRT heap). However, I cannot find a way to avoid it. Please, advise.

    Regards,

       Leonid


    • Edited by Minherz Wednesday, April 10, 2013 8:02 AM
    Wednesday, April 10, 2013 8:00 AM

Answers

  • Hi,

    As far as I know, the value or function in another language is meaningless for another language.

    For example, we can not call a native C++ function directly in .net environment. So far, we have many solution to call a native function in .net, like p/inovke, Com, CLI/C++. It looks very easy, but behind the codes, the complier did lots of work.

    Therefore, maybe you need more work to call a CLI/C++ function in Objective -C, because the complier will not help you to do this. First, we should make sure, Objective-C can call a native DLL in Win32, then make sure that Objective-C can call a .NET dll in Win32. Based on the two prerequisites, we can call a CLI/C++ dll. Because it mixed .NET and native.
     
    Best regards,
    Jesse


    Jesse Jiang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Elegentin Xie Wednesday, May 8, 2013 2:54 AM
    Thursday, April 11, 2013 5:55 AM
  • Hello,

    I have to say that expecting closely the ObjC code that fills the allocated pointer, I have found a line the overwrites the pointer with invalid data. Due some unclear reason it crashed in C++/CLI library code and not in ObjC and somehow I missed this invalid line.

    After a crash had happened in ObjC I found it at once. :(

    Thank you for everyone for your patience and endless attempts to direct me to the right place.


    Regards, Leo

    • Proposed as answer by Jesse Jiang Monday, April 15, 2013 6:45 AM
    • Marked as answer by Minherz Tuesday, April 16, 2013 6:35 AM
    Sunday, April 14, 2013 5:46 AM

All replies

  • Since you can't manipulate void*, you want to show us the code that actually uses the return value?

    Wednesday, April 10, 2013 11:35 AM
  • unsigned char* ptr = (unsigned char*)invoke_send_message(obj, bytes, &length);
    
    array<System::Byte>^ arr = gcnew array<System::Byte>(length);
    
    for (int i = 0; i < length; ++i)
        arr[i] = ptr[i];

    The exception in thrown on executing the last line in first loop iteration.

    Regards, Leo

    Wednesday, April 10, 2013 12:03 PM
  • Are you sure invoke_send_message returned a valid pointer? Look at the memory pointer to by ptr in the debugger and make sure it is valid.

    Guessing from the name you might be using win32 SendMessage, in case the message is sent to a different process, are you sure you are not getting a  pointer in that process's address space?

    Wednesday, April 10, 2013 1:56 PM
  • Did you inspect the value returned by your function?   Does it appear to be a memory address?   What is the value of length (and what was it before invoke_send_message) was called?

    The concept of mixing managed C++, unmanaged C++ and Objective C in the same program makes my head spin.   Are you sure that the buffer returned is property retained in objective c land.

    Wednesday, April 10, 2013 2:29 PM
  • Hello,

    This is exactly the core of the question. How do I handle a memory allocated by malloc (from library of OpenStep) in the managed (or unmanaged) code.

    If you know the answer, I will be glad to see it. I cannot provide you more info than I did.

    The method invoke_send_message treats passed bytes then allocates some buffer and returns the pointer to that buffer.


    Regards, Leo

    Wednesday, April 10, 2013 7:15 PM
  • This is a method implemented within OpenStep framework. It has nothing to do with WIN32 and SendMessage. See my another reply for a short description of what the method does.

    Regards, Leo

    Wednesday, April 10, 2013 7:16 PM
  • As far as unmanaged C/C++ is concerned bridging the gap as you have shown SHOULD work.

    I suspect strongly that your problem has NOTHING to do with the managed part and EVERYTHING to do with the unmanaged (Obj C) parts of your program.

    What is the value in "length?"   Do you have any indication (i.e., did you set it to zero first or such) that the function actually wrote into it?    What is in the memory value that is returned by that function?   Does the debugger show there's anything there or did it return 0 or some invalid address?

    You're really giving us NOTHING to go on here.


    • Edited by Ron Natalie Wednesday, April 10, 2013 7:30 PM
    Wednesday, April 10, 2013 7:30 PM
  • Hi,

    As far as I know, the value or function in another language is meaningless for another language.

    For example, we can not call a native C++ function directly in .net environment. So far, we have many solution to call a native function in .net, like p/inovke, Com, CLI/C++. It looks very easy, but behind the codes, the complier did lots of work.

    Therefore, maybe you need more work to call a CLI/C++ function in Objective -C, because the complier will not help you to do this. First, we should make sure, Objective-C can call a native DLL in Win32, then make sure that Objective-C can call a .NET dll in Win32. Based on the two prerequisites, we can call a CLI/C++ dll. Because it mixed .NET and native.
     
    Best regards,
    Jesse


    Jesse Jiang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Elegentin Xie Wednesday, May 8, 2013 2:54 AM
    Thursday, April 11, 2013 5:55 AM
  • Hello Jiang,

    Our product has a lot of interop between C/C++ libraries that are compiled in Microsoft Visual C.

    Most of interop goes from C/C++ toward ObjC (calling various methods). Providing (already) allocated buffer in either direction works fine. Buffer is always allocated on CRT heap (not managed). I expect that a problem here is that I am passing a CRT buffer allocated (on process heap) by binary of ObjC doesn't work when processed in managed code.

    I will try to split a code to have unmanaged part which will process the pointer. I will write my findings here.


    Regards, Leo

    Thursday, April 11, 2013 6:32 AM
  • Objective C is just a preprocessor that yields C.   The buffer should work just like the unmanaged C code that it is.   The returned information is either just allocated in free store with malloc() or it's allocated via malloc() and Objective C's internal garbage collector.    This was why I asked about it being "retained" which is Objective C-speak for keeping a reference to the allocated object so the garbage collector doesn't free it.    However, that I suspect is a red herring, even if not retained, the buffer should still have some data in it (even if it isn't anymore the right data).     I'm still expecting that the pointer value returned doesn't point to any sort of memory (it's either 0 or garbage).

    Thursday, April 11, 2013 11:13 AM
  • Hello Ron,

    I had already published a short version of the function implementation.

    It just malloc`ates a buffer of the size that NSInvocation defines to be the size of the return value and copies into it the return value stored in the NSInvocation object. Then the buffer is returned.

    Nothing sophisticated. Otherwise, I wouldn't ask the question.


    Regards, Leo

    Thursday, April 11, 2013 6:56 PM
  • Not in this thread you didn't.   You still have't indicated in the debugger if the memory dump at the location that appears to be the return value of that function is valid memory.    
    Friday, April 12, 2013 9:42 PM
  • Hello,

    I have to say that expecting closely the ObjC code that fills the allocated pointer, I have found a line the overwrites the pointer with invalid data. Due some unclear reason it crashed in C++/CLI library code and not in ObjC and somehow I missed this invalid line.

    After a crash had happened in ObjC I found it at once. :(

    Thank you for everyone for your patience and endless attempts to direct me to the right place.


    Regards, Leo

    • Proposed as answer by Jesse Jiang Monday, April 15, 2013 6:45 AM
    • Marked as answer by Minherz Tuesday, April 16, 2013 6:35 AM
    Sunday, April 14, 2013 5:46 AM