How to pass a pointer to an integer in C #

I have a C API with a signature:

int GetBuffer(char* buffer, int* maxSize) 

In C, I will call it as follows:

 char buffer[4096]; int maxSize = 4096; GetBuffer(buffer, &maxSize); 

maxSize is set to the size of the buffer and is set with the actual size filled.

I need to call it from C #. How to do it in "safe mode"?

+4
source share
4 answers

One option is to simply use the C # pointer types - this requires the unsafe block (or the modifier for the method / class) and compilation with /unsafe :

 [DllImport(...)] static extern int GetBuffer(byte* buffer, ref int maxSize); 

A buffer can be allocated in several different ways. One could use a fixed heap array:

 fixed (byte* buffer = new byte[4096]) { int maxSize = buffer.Length; GetBuffer(buffer, ref maxSize); } 

Another is to use stackalloc , although this is only possible for small buffers:

 byte* buffer = stackalloc byte[4096]; int maxSize = 4096; GetBuffer(buffer, ref maxSize); 

This particular approach is almost identical to your C code in terms of performance and distribution patterns.

Another option is to use marshaling for heap arrays and completely avoid pointers.

 [DllImport(...)] static extern int GetBuffer([Out] byte[] buffer, ref int maxSize); byte[] buffer = new byte[4096]; int maxSize = buffer.Length; GetBuffer(buffer, ref maxSize); 
+4
source

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(); 
+3
source

The presence of a handle to the pointer does not match the "safe mode" model. If the resource is not managed by the Framework, it is unsafe.

+2
source

You need to use the so-called P \ Invoke and generate a function declaration to reference the C function in the Dll from C #.

However, you must be very careful when transferring buffers to / from unmanaged code. The framework will take care of some things for you, but you may need to make sure that the memory you pass to the unmanaged call is not moved by the garbage collector.

 [DllImport("Kernel32.dll", SetLastError=true)] static extern Int32 GetBuffer(byte[] buffer,ref Int32 maxSize); 

And use it:

 byte[] myBuf = new myBuf[4096]; Int32 maxSize = myBuf.Length; GetBuffer(myBuf, ref maxSize); 
+2
source

All Articles