2

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#

1 Answer 1

2

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);
}
Sign up to request clarification or add additional context in comments.

10 Comments

Updated w/ more preferable solution.
Your text still says "use char array".
@RamanZhylich- Thanks a lot for reply. But after trying you solution I got this exception in my C3 application where I am calling the marshelled function -- Cannot marshal 'parameter #2': Invalid managed/unmanaged type combination (this value type must be paired with Struct).
You should use struct instead of class
Also try to pass it as a ref paramter, i.e public static extern void GetValue([MarshalAs(UnmanagedType.LPStr)]StringBuilder sbOut, ref Parameters sbIn);
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.