I have a DLL file that is written in C. I am try to use C DLL in my c# code. C program method return int** . int** in c and int[][] in c# is same?
I am getting an error while returning a value from c program.
c method
__declspec(dllexport) int someMethod
(
size_t *foo,
int **bar
)
{
*foo = 10;
**bar = 10;
}
My c# code
[DllImport(#"my.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true, BestFitMapping = true, EntryPoint = "someMethod")]
public unsafe static extern int someMethod
(
out Int16 foo,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(JaggedArrayMarshaler))]
out int[][] bar
);
C's int** and C#'s int[][] are similar in concept, but different at the binary level:
int** is a pointer to pointer, into the raw data in unmanaged heap memory.
int[][] is a managed reference to a managed array of managed references to managed arrays; each points to the array's header (which contains its length) instead of its raw data.
I don't know what would be easiest to marshal for C#. Can SAFEARRAY be nested? If so, it would probably easily map to C# arrays.
The solution that's sure to work is to use a C++/CLI DLL as glue between the two codes, to convert the int** into a cli::array<cli::array<int>^>^ (which involves copying the pointed data) before returning to C#.
Assuming the C function prototype is correct, I think you should declare it thusly on the C# side:
public unsafe static extern int someMethod
(
out Int16 foo,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0, ArraySubType=UnmanagedType.I2)]
out int[] bar
);
However, I fear a memory leak. I'm not sure how the unmanaged array can be deallocated.
Related
I am working on C#.Net application which uses C-based library. As it needs C# Wrapper I am implementing code to marshal functions from C-based library to be accessible in C# and map data type correctly.
I have a function in library which Takes A char array by reference, The function contains logic to update array with values in it. So, At function call we can pass null array and access result value after its been called.
Objective: to pass null char array and return value by reference
The C-dll function:
int function_call(char ** var);
The C function call code:
char *name = NULL;
int val = function_Call(&name);
The C# wrapper code:
[DllImport("mylibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int function_call([In] string[] val);
The C# function call code:
string[] name = null;
int ret = function_call(name);
I came across similar queries :
How to get char** using C#? [duplicate]
How do I marshal a pointer to an array of pointers to structures?
marshaling char**
C# equivalent to C const char**
Tried all of them but did not work. returns null value.
Is there a simple working way to marshal Char ** ?
You can simply marshal it as IntPtr :
[DllImport("mylibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int function_call(IntPtr val);
Just that on function call side, allocate mem to pointer and to access the data held by pointer : Marshal data from an unmanaged block of memory to the type specified by a generic type parameter.
I have a large library written in C that I would like to use as a DLL in a C# program. Most of the C code will be used by the libraries own functions, but I do need one function to be able to be called from the C# project.
So there's an example C function below
__declspec(dllexport) char* test(char* a){
char* b = "World";
char* result = malloc(strlen(a) + strlen(b) + 1);
strcpy(result, a);
strcpy(result, b);
return result;
}
Now in the C# code I have got using System.Running.InteropServices;
and also [DllImport("mydll.dll")] but I'm not sure how to declared the function.
public static extern char* test(char* a); obviously doesn't work because C# doesn't support pointers like C does.
So how should I pass a string to this C function and have it return a string as well?
You're looking for a MarshalAs attribute:
[DllImport("mydll.dll")]
static public int test([MarshalAs(UnmanagedType.LPStr)]String a);
As for returning a dynamically allocated C string, bad idea. How will you reliably de-allocate the string? It's a recipe for a memory leak. Allocate a byte array in C#, pin it and pass it to the C code along with its size so the C code can copy the result into it. Then convert to a string using System.Text.Encoding.ASCII.GetString().
I know this can be done by mallocing in C, passing malloced pointer to delegate with parameter type IntPtr, marshalling to string[] and then freeing malloced memory with separate, exported C-function from managed code.
My question is: Can this be done simpler way? E.g. :
C# delegate parameter is of type string[]?
no separate free function to call from managed code
EDIT: I tried with delegate signature:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
MyManagedDelegate(string[] values, int valueCount)
and fucntion in C:
void NativeCallDelegate(char *pStringValues[], int nValues)
{
if (gSetStringValuesCB)
gSetStringValuesCB(pStringValues, nValues);
}
calling it in C:
char *Values[]= {"One", "Two", "Three"};
NativeCallDelegate(Values, 3);
This results in that i can use only 1st string in array.
Here's how to do it properly, I'll give a full example so it's reproductible.
The C side
typedef void(*setStringValuesCB_t)(char *pStringValues[], int nValues);
static setStringValuesCB_t gSetStringValuesCB;
void NativeCallDelegate(char *pStringValues[], int nValues)
{
if (gSetStringValuesCB)
gSetStringValuesCB(pStringValues, nValues);
}
__declspec(dllexport) void NativeLibCall(setStringValuesCB_t callback)
{
gSetStringValuesCB = callback;
char *Values[] = { "One", "Two", "Three" };
NativeCallDelegate(Values, 3);
}
Nothing fancy here, I just added the necessary glue code and left the rest alone.
The C# side
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void MyManagedDelegate(
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 1)]
string[] values,
int valueCount);
[DllImport("NativeTemp", CallingConvention = CallingConvention.Cdecl)]
public static extern void NativeLibCall(MyManagedDelegate callback);
public static void Main()
{
NativeLibCall(PrintReceivedData);
}
public static void PrintReceivedData(string[] values, int valueCount)
{
foreach (var item in values)
Console.WriteLine(item);
}
The trick lies in the marshaling part:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void MyManagedDelegate(
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 1)]
string[] values,
int valueCount);
The MarshalAs attribute tells the .NET marshaler the following:
UnmanagedType.LPArray You're getting an array...
ArraySubType = UnmanagedType.LPStr ...of standard C strings...
SizeParamIndex = 1 ...and the size of that array is specified by the second parameter.
The C strings are copied and converted to System.String instances by the .NET marshaler before the invocation of your C# method. So if you need to pass dynamically generated strings to C#, you malloc them, then you call gSetStringValuesCB, and you can free them immediately afterwards, all from the C code, as .NET has its own copy of the data.
You can refer to the docs:
UnmanagedType.LPArray:
A pointer to the first element of a C-style array. When marshaling from managed to unmanaged code, the length of the array is determined by the length of the managed array. When marshaling from unmanaged to managed code, the length of the array is determined from the MarshalAsAttribute.SizeConst and MarshalAsAttribute.SizeParamIndex fields, optionally followed by the unmanaged type of the elements within the array when it is necessary to differentiate among string types.
UnmanagedType.LPStr:
A single byte, null-terminated ANSI character string. You can use this member on the System.String and System.Text.StringBuilder data types.
MarshalAs.SizeParamIndex:
Indicates the zero-based parameter that contains the count of array elements, similar to size_is in COM.
I came up with far from optimal solution:
public delegate void MyManagedDelegate([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeConst=10)]string[] values, int valueCount);
This is not working if called like this:
char *Values[]= {"One", "Two", "Three"};
NativeCallDelegate(Values, 3);
I could have fixed size 10 array where the values are copied and that is always passed to delegate. This is not what I want. I wonder if there is good solution to this...
I have two c++ functions that I want to DllImport:
bool SendString(const char* pSendStr, long strSize);
bool ReadString(char* pReadStr, long& readStrSize);
There are a lot of articles that write how to DllImport strings.
Alas quite often I see different replies to the same question.
For instance some say if a c++ function returns a a char* and an int* strLen, then some people say I should use a StringBuilder in my dllImport statement and others say return byte[], some have a marshall statement in the dllImport, some don't. Some answers seem needed because of old C# / .net versions.
So the question is: If the dll call from c++ is fairly straightforward, without strange calling conventions, or other strange items, what should the corresponding DllImport functions be if you have output char* and size or input char * and size?
c++ .h
bool SendString(const char* pSendStr, long strSize);
bool ReadString(char* pReadStr, long& readStrSize);
What are the corresponding DllImports? replace the instr and outstr with string? stringbuilder? char[]? byte[]? Is any marshal statement needed?
bool SendString(const char* pSendStr, long strSize);
This function is the easy one. The text is sent from the caller to the callee. The p/invoke is declared like this:
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern bool SendString(string SendStr, int Len);
Note that I'm assuming the cdecl calling convention since that is the default for C++ code. And also do note that long in C++ on Windows is 32 bits wide. So it matches int in C#.
When you call the function you need to pass the string and its length. However, the normal convention is for null-terminated strings to be used so the length parameter is not needed. I'd declare the unmanaged function like this:
bool SendString(const char* pSendStr);
And the p/invoke like this:
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern bool SendString(string SendStr);
The other function is a little more complex. You've declared it like this:
bool ReadString(char* pReadStr, long& readStrSize);
Here the caller allocates the buffer which is populated by the callee. You can use StringBuilder for the text and let the marshaler do the work for you. The p/invoke is:
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern bool ReadString(StringBuilder ReadStr, ref int Len);
The convention is that you supply the length of the provided buffer. In turn the function will let you know how many characters it wrote. You'd call the function like this:
int len = 256;
StringBuilder ReadStr = new StringBuilder(len);
bool succeeded = ReadString(ReadStr, ref len);
if (succeeded)
{
string str = ReadStr.ToString();
}
As leppie wrote, what you usually want is:
[DllImport(my.dll)]
static extern bool SendString(string sendString, int stringSize);
[DllImport(my.dll)]
static extern bool ReadString(StringBuilder readString, ref int readStringSize);
This would do automatic conversion to Unicode (and back) for you.
If you want precise access to your char*, you would use byte[]. This way no conversion is done and you have more control on what is going on. Usually you won't need that. One use case might by when your char* can include \0 chars.
Suppose I have a structure:
typedef struct {
float x;
float y;
float z;
int ID;
} Vertex;
and a C++ function:
float first(Vertex* ptr, int length){ //really silly function, just an example
Vertex u,v;
u.x = ptr[0].x; //...and so on, copy x,y,z,ID
v.x = ptr[1].x;
return (u.x * v.x + u.y * v.y + u.z * v.z);
}
Vertex* another(float a, int desired_size){
Vertex v = (Vertex*)malloc(desired_size*sizeof(Vertex));
v[0].x = a;
v[1].x = -a; //..and so on.. make some Vertices.
return v;
}
First - my IDE. I'm using Visual Studio 2010, building a C# (4.0) application; The C++ part is also built in VS2010.
I know how to build a DLL of C/C++ code and use it in C# application, but until today I used only primitive arguments and return values like:
[DllImport("library.dll", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern int simple(int a, int b);
Today I need to pass an array of structs (as in the example above).. and perhaps also receive one back..
How to I "translate" a C# class to a C struct (and vice versa) ??
The struct can be declared like this:
[StructLayout(LayoutKind.Sequential)]
public struct Vertex {
public float x;
public float y;
public float z;
public int ID;
}
Next you need to settle on a calling convention. Your C++ code is almost certainly compiled with cdecl. Let's stick with that.
The function first is easy to call from C#:
[DllImport("library.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern float first(Vertex[] vertices);
Note that you should not use SetLastError here–that's for Windows API functions. And there's no need to set the CharSet since there is no text here.
Now, for another things get more complex. If you can allocate the memory in the C# code then that is definitely the way to go.
void PopulateVertices(Vertex *vertices, int count)
{
for (int i=0; i<count; i++)
{
vertices[i].x = ....
}
}
On the C# side you declare it like this:
[DllImport("library.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void PopulateVertices(Vertex[] vertices, int count);
and call it like this
Vertex[] vertices = new Vertex[2];
PopulateVertices(vertices, vertices.Length);
If you don't want to allocate on the C# side of the fence then do it like this:
Return a pointer from the C++ code and allocate it with CoTaskMemAlloc.
In C# declare the return value of the imported function as IntPtr.
Use Marshal.PtrToStructure and some pointer arithmetic to marshal the return array into a C# array.
Call Marshal.FreeCoTaskMem to free the memory allocated in the native module.
But if you want my advice, try and stick to allocating the array in the managed code.
It should be this easy:
[StructLayout(LayoutKind.Sequential)]
public struct Vertex {
float x;
float y;
float z;
int ID;
}
[DllImport("library.dll", CallingConvention=CallingConvention.StdCall)]
public static extern float first(Vertex[] verticies, int arrLen);
The issues you may run into would be if there is any packing done on the C version of the struct, and possibly the struct layout. If the layout doesn't match, you may want to change it to LayoutKind.Explicit and use the [FieldOffset(0)] attribute on each field. C would also have no idea, the length of the verticies array passed, so if that changes, you'd want to pass that along to the method.
To get an array back:
[DllImport("library.dll", CallingConvention=CallingConvention.StdCall)]
public static extern Vertex[] another(float a);
The marshaler handles all of the memory issues when passing arguments in, but returning the array it can't do anything. Since the memory is allocated on the unmanaged heap, the GC has no idea about it, and you will wind up with a memory leak. The marshaller will simply copy the native structs to the managed struct array, but it can't free the memory you've allocated with malloc.
The easiest way to get around it, if you can change the C++ code, would be to change the signature of another to take in an array of verticies (and the length of the array) instead of returning one. I don't need to write out any code for you that does this, #DavidHeffernan has already done this in his answer, the part of the break.