Sending pointer to struct to C DLL

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
 
K

Kevin Aubuchon

[ 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);
 
K

Kevin Aubuchon

[ 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);
 
W

Willy Denoyette [MVP]

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
 
L

Leo

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top