Mike Stone
Mike Stone

Reputation: 319

Calling C function with struct in C# - what am I doing wrong?

I thought this one was fairly straight forward but still trying to understand all of this and having some issues.

I don't know much about the C function b/c i've been given limited information.

Here is the function call in C:

int GetCard(CardInfo card);

Here is the request structure:

typedef struct _tCardInfo
{
    char CardNumber[80];
    char isExist;

} TCardInfo, *pTCardInfo;

I want to pass the card number to see if it exists.

So in C# I did the following:

public struct CardInfo
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
    public string cardNumber;

    public byte isExist;
}

[DllImport("card.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern int GetCardInfo(ref CardInfo cardInfo);

Then in the c# method:

CardInfo cardInfo = new CardInfo();

cardInfo.cardNumber = "1234567890"; 

int success = GetCardInfo (ref cardInfo);

The good thing about the DLL that I'm calling is it generates a log file. When I execute the call, the log tells me that I'm hitting the DLL but it is not passing the card number which then sets a message saying the card number was not passed.

Any help is greatly appreciated. Thanks!

Upvotes: 1

Views: 1082

Answers (3)

Jon Watte
Jon Watte

Reputation: 7198

The problem is that you're requesting TChar marshaling, but the DLL requires 8-byte characters. Change the C struct to wchar_t.

Also, use Visual Studio to set a breakpoint in your DLL, and actually inspect the data when it comes in! Visual Studio can debug across .NET/native boundaries, which is super cool!

Upvotes: 1

toderik
toderik

Reputation: 479

Try to create the .Net struct like this:

    [StructLayout(LayoutKind.Sequential)]
    public struct CardInfo
    {
        [MarshalAs(UnmanagedType.AnsiBStr, SizeConst = 80)]
        public string cardNumber;

        [MarshalAs(UnmanagedType.I1)]
        public sbyte isExist;
    }

And for the function declaration: try not to use the CallingConvention and CharSet in the DLL import, and use the [In, Out] attributes before the parameter. Like this:

[DllImport("card.dll")]
public static extern int GetCardInfo([In, Out] CardInfo cardInfo);

Upvotes: 0

tom.maruska
tom.maruska

Reputation: 1481

Try to add attribute StructLayout for struct

[StructLayout(LayoutKind.Sequential)]
public struct CardInfo
{
...

Upvotes: 0

Related Questions