Sending pointer to struct to C DLL

  • Thread starter Thread starter Leo
  • Start date Start date
L

Leo

Hello,

I have a C dll with a method signature of:

int activate(datastruct *data)

where datastruct is defined as:

typedef struct datastruct {
long result;
unsigned char data[1024];
char id[20];
} datastruct;

In C#, I have a small test class defining a struct and using the
method. The small class is this:

using System;
using System.Runtime.InteropServices;

namespace DLLTest
{
[StructLayout(LayoutKind.Sequential)]
public struct datastruct
{
public long result;
public char [] data;
public char [] id;
};

public class Tester
{
[DllImport(@"C:\DSDLL.DLL", CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall, ThrowOnUnmappableChar =
true)]
public static extern int activate(???);

[STAThread]
public static void Main(String [] args)
{
datastruct ds = new datastruct();

ds.result = 0;
ds.data = new char[1024];
ds.id = new char[32];

int i = Tester.activate(<pointer to ds???>); }
}
}

The C# code is being rewritten from C++ and the C++ code works just
fine when passing the pointer to activate(). Unfortunately I don't
have the luxury of changing the C DLL.

The C DLL should be filling ds.data with chars and ds.result with a
value, which it does in the C++ version [its an old DLL, been around
for years].

I have tried a variety of mechanisms to fill in the question marks,
all met with varying degrees of failure ranging from compiler errors
to runtime exceptions in the receiving DLL. I must be overlooking
something simple but I cannot see what it is. Maybe this isn't
possible?

I've checked the P/Invoke section and examples in MSDN (VS.NET 2003)
and the many prior postings of similar questions in this group but
have not been successful in applying them to this case.

Would someone mind reviewing the above and pointing me in the right
direction?

I appreciate any suggestions.

Thank you,
-L
 
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
struct datastruct {
long result;
[MarshalAs(UnmanagedType.ByValTStr ,SizeConst=1024)]
string data;
[MarshalAs(UnmanagedType.ByValTStr ,SizeConst=20)]
string char;
};


[DllImport("C:\\DSDLL.DLL", SetLastError=true)]
public static extern int activate(ref datastruct ds);
 
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
struct datastruct {
long result;
[MarshalAs(UnmanagedType.ByValTStr ,SizeConst=1024)]
string data;
[MarshalAs(UnmanagedType.ByValTStr ,SizeConst=20)]
string char;
};


[DllImport("C:\\DSDLL.DLL", SetLastError=true)]
public static extern int activate(ref datastruct ds);
 
This is not correct, long is 64 bit in C#, 32 bit in C.
So, long result;
should look like:
int result;

Willy.


Kevin Aubuchon said:
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
struct datastruct {
long result;
[MarshalAs(UnmanagedType.ByValTStr ,SizeConst=1024)]
string data;
[MarshalAs(UnmanagedType.ByValTStr ,SizeConst=20)]
string char;
};


[DllImport("C:\\DSDLL.DLL", SetLastError=true)]
public static extern int activate(ref datastruct ds);

--
kevin aubuchon
www.aubuchon-design.com


Leo said:
Hello,

I have a C dll with a method signature of:

int activate(datastruct *data)

where datastruct is defined as:

typedef struct datastruct {
long result;
unsigned char data[1024];
char id[20];
} datastruct;

In C#, I have a small test class defining a struct and using the
method. The small class is this:

using System;
using System.Runtime.InteropServices;

namespace DLLTest
{
[StructLayout(LayoutKind.Sequential)]
public struct datastruct
{
public long result;
public char [] data;
public char [] id;
};

public class Tester
{
[DllImport(@"C:\DSDLL.DLL", CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall, ThrowOnUnmappableChar =
true)]
public static extern int activate(???);

[STAThread]
public static void Main(String [] args)
{
datastruct ds = new datastruct();

ds.result = 0;
ds.data = new char[1024];
ds.id = new char[32];

int i = Tester.activate(<pointer to ds???>); }
}
}

The C# code is being rewritten from C++ and the C++ code works just
fine when passing the pointer to activate(). Unfortunately I don't
have the luxury of changing the C DLL.

The C DLL should be filling ds.data with chars and ds.result with a
value, which it does in the C++ version [its an old DLL, been around
for years].

I have tried a variety of mechanisms to fill in the question marks,
all met with varying degrees of failure ranging from compiler errors
to runtime exceptions in the receiving DLL. I must be overlooking
something simple but I cannot see what it is. Maybe this isn't
possible?

I've checked the P/Invoke section and examples in MSDN (VS.NET 2003)
and the many prior postings of similar questions in this group but
have not been successful in applying them to this case.

Would someone mind reviewing the above and pointing me in the right
direction?

I appreciate any suggestions.

Thank you,
-L
 
Kevin, Willy,

Thank you both very much for your assistance -- I appreciate your time
and the answer that got me going again!

Thank you,
-L

Willy Denoyette said:
This is not correct, long is 64 bit in C#, 32 bit in C.
So, long result;
should look like:
int result;

Willy.


Kevin Aubuchon said:
[ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
struct datastruct {
long result;
[MarshalAs(UnmanagedType.ByValTStr ,SizeConst=1024)]
string data;
[MarshalAs(UnmanagedType.ByValTStr ,SizeConst=20)]
string char;
};


[DllImport("C:\\DSDLL.DLL", SetLastError=true)]
public static extern int activate(ref datastruct ds);

--
kevin aubuchon
www.aubuchon-design.com


Leo said:
Hello,

I have a C dll with a method signature of:

int activate(datastruct *data)

where datastruct is defined as:

typedef struct datastruct {
long result;
unsigned char data[1024];
char id[20];
} datastruct;

In C#, I have a small test class defining a struct and using the
method. The small class is this:

using System;
using System.Runtime.InteropServices;

namespace DLLTest
{
[StructLayout(LayoutKind.Sequential)]
public struct datastruct
{
public long result;
public char [] data;
public char [] id;
};

public class Tester
{
[DllImport(@"C:\DSDLL.DLL", CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall, ThrowOnUnmappableChar =
true)]
public static extern int activate(???);

[STAThread]
public static void Main(String [] args)
{
datastruct ds = new datastruct();

ds.result = 0;
ds.data = new char[1024];
ds.id = new char[32];

int i = Tester.activate(<pointer to ds???>); }
}
}

The C# code is being rewritten from C++ and the C++ code works just
fine when passing the pointer to activate(). Unfortunately I don't
have the luxury of changing the C DLL.

The C DLL should be filling ds.data with chars and ds.result with a
value, which it does in the C++ version [its an old DLL, been around
for years].

I have tried a variety of mechanisms to fill in the question marks,
all met with varying degrees of failure ranging from compiler errors
to runtime exceptions in the receiving DLL. I must be overlooking
something simple but I cannot see what it is. Maybe this isn't
possible?

I've checked the P/Invoke section and examples in MSDN (VS.NET 2003)
and the many prior postings of similar questions in this group but
have not been successful in applying them to this case.

Would someone mind reviewing the above and pointing me in the right
direction?

I appreciate any suggestions.

Thank you,
-L
 
Back
Top