I have a C API with the signature:
int GetBuffer(char* buffer, int* maxSize)
In C, I will call it this way:
char buffer[4096];
int maxSize = 4096;
GetBuffer(buffer, &maxSize);
maxSize is set to the buffer size, and set with the actual size filled.
I need to call it from C#. How do I do that under "safe mode"?
Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined.
No, it is no valid to assign a pointer to an integer. It's a constraint violation of the assignment operator (C99, 6.5. 16.1p1). A compiler has the right to refuse to translate a program with a pointer to integer assignment.
Passing Pointers to Functions in C++ C++ allows you to pass a pointer to a function. To do so, simply declare the function parameter as a pointer type.
Pointers are passed by value as anything else. That means the contents of the pointer variable (the address of the object pointed to) is copied.
One option is simply to use C# pointer types - this requires unsafe
block (or modifier on method/class), and compiling with /unsafe
:
[DllImport(...)]
static extern int GetBuffer(byte* buffer, ref int maxSize);
Buffer can be allocated in several different ways. One would be to use a pinned heap array:
fixed (byte* buffer = new byte[4096])
{
int maxSize = buffer.Length;
GetBuffer(buffer, ref maxSize);
}
Another is to use stackalloc
, though this is only feasible for small buffers:
byte* buffer = stackalloc byte[4096];
int maxSize = 4096;
GetBuffer(buffer, ref maxSize);
This particular approach is virtually identical to your C code in terms of performance and allocation patterns.
Another option altogether is to use marshaling for heap arrays, and avoid pointers entirely.
[DllImport(...)]
static extern int GetBuffer([Out] byte[] buffer, ref int maxSize);
byte[] buffer = new byte[4096];
int maxSize = buffer.Length;
GetBuffer(buffer, ref maxSize);
This should work without unsafe code.
extern int GetBuffer(IntPtr buffer, ref int bufSize);
// ...
byte[] buf = new byte[kBufSize];
GCHandle handle = GCHandle.Alloc(buf, GCHandleType.Pinned); // possibly expensive call
IntPtr p = handle.AddrOfPinnedObject();
int size = buf.Length;
int ret = GetBuffer(p, ref size);
handle.Free();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With