0

I have a native C++ function that I have to call from my C# code, the C++ function looks like this:

__declspec(dllexport) int getCameraFrame(void *buffer);

Calling the function in C++ looks like this:

unsigned char* data = new unsigned char[640 * 480 * 4];
getCameraFrame(data);

From C# I import the function with PInvoke as:

[DllImport("CameraSDK.dll")]
public static extern int getCameraFrame(???);

What do I use as a parameter here, and how would I call the function from my C# code?

byte[] buffer;
getCameraFrame(out buffer); //???

UPDATE

I have tried using string, byte[], char[], IntPtr as parameters but I keep getting a PInvokeStackImbalance exception.

A call to PInvoke function 'Test!Test.Form1::getCameraFrame' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

UPDATE - Solved

With the answers given by David and Michael, I've managed to solve my issue with the below code

[DllImport("CameraSDK.dll", CallingConvention.Cdecl)]
public static extern int getCameraFrame([Out] StringBuilder buffer);

StringBuilder data = new StringBuilder(1024 * 768 * 4)
int result = getCameraFrame(data);

David, your answer was indeed correct, note that my StringBuilder init is 1024 * 768 * 4 (and not 640 * 480 * 4 - this is what was throwing the AccessViolationException) - in the C++ code the buffer is scaled from (1024 * 768 * 4) to (640 * 480 * 4) - I must have missed that part, so, that's my bad.

I'm able to get the raw data but cannot convert it to a bitmap (raw data is in some weird format) but that is another question.

Thanks

3
  • 1
    Take a look at [here][1] Hope it helps. [1]: stackoverflow.com/a/15528053/2928544 Commented Jul 28, 2015 at 13:19
  • @raidensan - Very interesting thanks, but still no luck, I keep getting a PInvokeStackImbalance exception Commented Jul 28, 2015 at 13:32
  • I reverted your edits since they change the question and make the answers look stupid. Commented Jul 29, 2015 at 6:43

2 Answers 2

2

I have a following working code:

C++ definition:

__declspec(dllexport) void SendRenderedImage(byte buffer[]);

C# declaration

[DllImport("External.dll", EntryPoint = "SendRenderedImage", CallingConvention = CallingConvention.Cdecl)]
public static extern void SendRenderedImage(
    [MarshalAs(UnmanagedType.LPArray)] byte[] buffer
);

C# usage:

SendRenderedImage(new byte[10]);

Hope it helps.

Sign up to request clarification or add additional context in comments.

7 Comments

Right, one step closer, I'm able to call the native function, however, when I call it a second time I get a AccessViolationException - Attempted to read or write protected memory - any ideas?
Can you show the code which calls the function? Do you get the exception before you reach the C++ code?
I have included the C++ & C# bits that calls the function, the exception is thrown on the (with the modified code from above) getCameraFrame(data) line.
When you call the function, you don't need the out keyword. And in your example you call the function with uninitialized byte[] buffer, you have to do new byte[n] first and, probably, fill the data in.
@Michael No. The data flows out. No need to initialize it.
|
0

I'd declare it like this:

[DllImport(dllname, CallingConvention = ???)]
public static extern int getCameraFrame(
    [Out] byte[] buffer
);

Call the function like this:

byte[] data = new byte[640 * 480 * 4];
int retval = getCameraFrame(data);

Note that you need to work out what the calling convention is. On the face of it, it looks like cdecl.

I use the [Out] attribute to indicate that the data flows from callee to caller. However, since the marshaller will simply pin the array, this has no discernible impact. It does at least document the intent for future readers.

Update

You say in comments that you encounter an access violation when using this code The code here is accurate given the information you have provided. The problem therefore must be in something we cannot see. Perhaps the library has not been initialized. Perhaps the funcions are instance methods. Or perhaps there is some other problem that cannot be discerned.

You need to look beyond what you have shown in the question. Were I in your place I'd start by making a complete C++ program that uses the library, to prove that the library works and that you know what sequence of calls to make. Then I'd translate that to C#.

7 Comments

How can I determine what the calling convention is? The function's return type is int, I'll edit my question... Putting [Out] before the byte[] parameter takes me back to square one i.e. getting a PInvokeStackImbalance exception.
Have you pasted the exact declaration yet? The question history makes me doubt that we've seen the actual C++ code yet.
I have included all the code that relates to my issue, I have no idea what the function body looks like because it is in an SDK dll file (which is obfuscated)
The calling convention is indeed Cdecl
Given the information in the question, my answer is accurate.
|

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.