3

consider following setup: c# application with c++ library. c# elements are filled from c++ via callback. on c# side callback is defined like this:

void callbackTester(IntPtr pData, UInt32 length)
{
    int[] data = new int[length];
    Marshal.Copy(pData, data, (int)0, (int)length);
    //using data.. on c#
}

now, on c++ side callback is defined like this:

typedef void (__stdcall *func)(uint8_t* pdata, uint32_t length);

and c++ is using callback like this:

void onData()
{
    std::vector<uint8_t> dataToCallback;
    // fill in dataToCallback
    _callback(&(dataToCallback[0]), dataToCallback.size());
    // where _callback is a pointer to that c# function
}

my task: get array from c++ side on c# side using callback.

so, when c++ object is calling onData() function, it calls my callback from c#. so far so good. i have made a c++ tester program, which uses this, and i am receiving array correctly on callback side. if i am using it on c# tester, i am receiving crap.

for example: if i am sending uint8_t array of {1, 1}, i am getting {1, 1} for c++ tester, and i am getting {0xfeeeabab, 0xfeeefeee} on c# side... obviously, the conversion between uint8_t* c++ pointer and IntPtr c# is working not as i expect.

any suggestions? thanks a lot.

6
  • As far as I know uint8_t != (C#)int. The correct one shouldbe byte. Also std::vector is not an array and I doubt you can copy it to C# like that. Commented Apr 8, 2014 at 13:41
  • 1
    @floele You are mixed with where you are right and wrong. int!=uint8_t, int is a 32-but integer. byte[] in C# will work. The underlying data structure for std::vector is an array so this will work fine. protip: use std::vector.data instead of &(dataToCallback[0]). Commented Apr 8, 2014 at 13:46
  • uint8_t is "casted" to IntPtr and not UIntPtr, because Marshal.Copy accepts only IntPtr. how else can you get data on c# side? Commented Apr 8, 2014 at 13:51
  • @etwas77 IntPtr in C# is a misnomer, it is really equivilent to a c++ void*. It is just a memory location. Commented Apr 8, 2014 at 13:52
  • first, what you're trying to do is to call a c# function from C++ via the function pointer of that C# function? Commented Apr 8, 2014 at 13:58

2 Answers 2

1

The issue appears to be that C++ uint8_t is an unsigned byte, and C# int is a signed 4 byte integer. So you have a simple mismatch of types. The C# type that matches uint8_t is byte.

Your callback should be:

void callbackTester(IntPtr pData, uint length)
{
    byte[] data = new byte[length];
    Marshal.Copy(pData, data, 0, (int)length);
}
Sign up to request clarification or add additional context in comments.

Comments

0

one thing to check is that on C# side you are expecting int-4 bytes per element ("int[] data") but on C++ you only allocating uint8-1 byte per element.

adjust the allocation or length usage, you could be getting access violation, that why you see magic bytes [1].

[1] http://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_debug_values

2 Comments

not sure what you mean. i supply proper data on c++ side (i see it in a debugger). when i land on c# side (still on debugger) and initialize array there using IntPtr and length, i get that thing. length is tranferred ok. obviously IntPtr points not to correct address.. what is wrong?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.