How to call C# delegate to pass array of strings from native C simplest way?

char m

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.

Lucas Trzesniewski

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.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to call Swift from an Objective C project App Delegate?

From Dev

Simplest way to pass a lambda as a method parameter in C++17

From Dev

How to call C# from C to pass array of structs having arrays as members?

From Dev

How to pass two Strings from Swift to a C++ function, and getting an array of Integers?

From Dev

How to pass an array of Swift strings to a C function taking a char ** parameter

From Dev

How to pass an array of strings through a COM (C++) API

From Dev

How to pass parameter from an array in c#?

From Dev

How to pass from array to vector - c++

From Dev

Simplest way to populate class from query in C#

From Dev

How to pass a pointer from C# to native function in DLL?

From Dev

C - Pass Array of Strings as Function Parameter

From Dev

how to pass an array of strings from jQuery to controller

From Dev

How to pass an element from a array of strings to a thread?

From Dev

C# pass parameter to delegate

From Dev

Print from array of strings in C

From Dev

C# Await in a delegate call

From Dev

How to pass linebreak from a variable in "ANSI-C" way?

From Dev

How to add keys and values to an array the simplest way

From Dev

What is the simplest way to prefix all strings in an array with a "!" (exclamation mark) in javascript?

From Dev

What is simplest way to convert :pluck or :collect results to array of strings in Rails?

From Dev

How to Declare a Delegate at runtime and call its method at runtime in C#?

From Dev

call c dll from delphi with strings

From Dev

Simplest way to use default argument in C

From Dev

How to extract integers from array of strings in C++

From Dev

C-How to read words from a text file into an array of strings

From Dev

How to extract integers from array of strings in C++

From Dev

How to add Strings from a Char Array to a String in C

From Dev

How to Change individual strings in an array of strings in C?

From Dev

C Way to Extract Variables from Strings

Related Related

  1. 1

    How to call Swift from an Objective C project App Delegate?

  2. 2

    Simplest way to pass a lambda as a method parameter in C++17

  3. 3

    How to call C# from C to pass array of structs having arrays as members?

  4. 4

    How to pass two Strings from Swift to a C++ function, and getting an array of Integers?

  5. 5

    How to pass an array of Swift strings to a C function taking a char ** parameter

  6. 6

    How to pass an array of strings through a COM (C++) API

  7. 7

    How to pass parameter from an array in c#?

  8. 8

    How to pass from array to vector - c++

  9. 9

    Simplest way to populate class from query in C#

  10. 10

    How to pass a pointer from C# to native function in DLL?

  11. 11

    C - Pass Array of Strings as Function Parameter

  12. 12

    how to pass an array of strings from jQuery to controller

  13. 13

    How to pass an element from a array of strings to a thread?

  14. 14

    C# pass parameter to delegate

  15. 15

    Print from array of strings in C

  16. 16

    C# Await in a delegate call

  17. 17

    How to pass linebreak from a variable in "ANSI-C" way?

  18. 18

    How to add keys and values to an array the simplest way

  19. 19

    What is the simplest way to prefix all strings in an array with a "!" (exclamation mark) in javascript?

  20. 20

    What is simplest way to convert :pluck or :collect results to array of strings in Rails?

  21. 21

    How to Declare a Delegate at runtime and call its method at runtime in C#?

  22. 22

    call c dll from delphi with strings

  23. 23

    Simplest way to use default argument in C

  24. 24

    How to extract integers from array of strings in C++

  25. 25

    C-How to read words from a text file into an array of strings

  26. 26

    How to extract integers from array of strings in C++

  27. 27

    How to add Strings from a Char Array to a String in C

  28. 28

    How to Change individual strings in an array of strings in C?

  29. 29

    C Way to Extract Variables from Strings

HotTag

Archive