Vikram
Vikram

Reputation: 1627

How to call a function in C code with Struct as parameter from C#

I have a struct in C file as shown below

struct Parameter{
    char param1[20];
    char param2[20];
}

and also a function in C file which takes this struct as parameter along with char* as another parameter as shown below

extern "C" __declspec(dllexport) void GetValue(char* opt,struct Parameter param);
void GetValue(char* opt, struct Parameter params)
{
printf("%s", params->param1);
}

I want to call it from my C# application using marshalling. I have created a similar struct in C#

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class Parameters
{      
    public string Param1 { get; set; }     
    public string Param1 { get; set; }   
}

and calling it in C# using the below method

 [DllImport(@"C:\Test\CTestDll.dll",CallingConvention = CallingConvention.Cdecl,CharSet=CharSet.Ansi)]      
 public static extern void GetValue([MarshalAs(UnmanagedType.LPStr)]StringBuilder sbOut, [MarshalAs(UnmanagedType.LPStruct)]Parameters sbIn);

but the result which is a print statement is printing null.I am not very good in C programming. Kindly help me to sort it out. Where I am wrong, Is it in the C function or marshalling from C#

Upvotes: 2

Views: 1156

Answers (1)

Raman Zhylich
Raman Zhylich

Reputation: 3697

The difference is that in C++ your structure contains raw chars, while in C# you class contains reference to string. MarshalAs attribute will use a char array instead of a reference to string:

unsafe static class Program
{

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Parameters
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public String Param1;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public String Param2;
}


[DllImport(@"CTestDll2.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void GetValue(StringBuilder sbOut, Parameters sbIn);


static void Main(string[] args)
{
    var p = new Parameters
    {
        Param1 = "abc",
        Param2 = "dfc"
    };

    var s = new StringBuilder("some text");

    GetValue(s, p);
}

}

C++:

// CTestDll.h

#pragma once

#include <stdio.h>

extern "C" __declspec(dllexport) void GetValue(char* opt, struct Parameter param);

struct Parameter{
    char param1[20];
    char param2[20];
};

void GetValue(char* opt, struct Parameter params)
{
    printf("param1: %s, param2: %s, string: %s", params.param1, params.param2, opt);
}

Upvotes: 2

Related Questions