Interop question: how to pass a pointer to an unmanaged struct into C#?

R

Robert Rossney

I'm working with a very old-school application (written in MicroFocus Object
COBOL) that supports user extension functions. Before the app writes a
record to its database, it checks its configuration to see if an extension
function is configured. If one is, it loads the DLL whose name you've
specified in the configuration and calls a function with the same name,
passing it pointers to two structures.

The C function prototype of the function that the app calls looks like this:

void foo(struct STRUCT1 *sl, struct STRUCT2 *s2)

Because I want to do as little non-.NET development as possible, I've
figured out how to instantiate a C# COM object from within this function.
The goal is to have my C function create an instance of the COM class, pass
it the pointers to the two structs, and then do all of my actual
business-logic coding in C#.

However, I'm having a devil of a time getting to those structs from inside
my object. I know how I would define the struct if I were going to be
calling unmanaged code from managed code:

[StructLayout (LayoutKind.Sequential)]
public struct STRUCT1 {
[MarshalAs( UnmanagedType.ByValArray,
ArraySubType=UnmanagedType.AnsiBStr, SizeConst=10 )]
byte[] field1;
[MarshalAs( UnmanagedType.ByValArray,
ArraySubType=UnmanagedType.AnsiBStr, SizeConst=10 )]
byte[] field2;
...
}

But I'm calling managed code from unmanaged code. And I don't know how to
define this struct so that this C# function declaration:

public unsafe void MyFunc(STRUCT1* p1, STRUCT2* p2)

doesn't make the compiler produce this error:

error CS0208: Cannot take the address or size of a variable of a managed
type.

How can I mark the declaration of the struct so that the compiler knows that
I want it to be unmanaged?

I know that I can just create a byte array that's the size of my struct,
pass pointers to the array into my code, and then use offsets to update the
data in the array, but it seems really dumb to do thsat if there's another
way. Is there another way?

And, of course, is my conception of this problem all wrong?

Thanks in advance.

Bob Rossney
(e-mail address removed)
 
D

Drebin

Not sure if will ruin what you are doing, but if you declare the struct
members as static, it will compile. Will it work the way you want? Who
knows?!!! This compiles:


[StructLayout(LayoutKind.Sequential)]
public unsafe struct STRUCT1
{
[MarshalAs( UnmanagedType.ByValArray, ArraySubType=UnmanagedType.AnsiBStr,
SizeConst=10 )]
static unsafe byte[] field1;
[MarshalAs( UnmanagedType.ByValArray, ArraySubType=UnmanagedType.AnsiBStr,
SizeConst=10 )]
static unsafe byte[] field2;
}

[StructLayout(LayoutKind.Sequential)]
public unsafe struct STRUCT2
{
[MarshalAs( UnmanagedType.ByValArray, ArraySubType=UnmanagedType.AnsiBStr,
SizeConst=10 )]
static byte[] field1;
[MarshalAs( UnmanagedType.ByValArray, ArraySubType=UnmanagedType.AnsiBStr,
SizeConst=10 )]
static byte[] field2;
}
public unsafe class Class1
{
public unsafe void MyFunc(STRUCT1* p1, STRUCT2* p2)
{
}
}

hth


Robert Rossney said:
I'm working with a very old-school application (written in MicroFocus
Object
COBOL) that supports user extension functions. Before the app writes a
record to its database, it checks its configuration to see if an extension
function is configured. If one is, it loads the DLL whose name you've
specified in the configuration and calls a function with the same name,
passing it pointers to two structures.

The C function prototype of the function that the app calls looks like
this:

void foo(struct STRUCT1 *sl, struct STRUCT2 *s2)

Because I want to do as little non-.NET development as possible, I've
figured out how to instantiate a C# COM object from within this function.
The goal is to have my C function create an instance of the COM class,
pass
it the pointers to the two structs, and then do all of my actual
business-logic coding in C#.

However, I'm having a devil of a time getting to those structs from inside
my object. I know how I would define the struct if I were going to be
calling unmanaged code from managed code:

[StructLayout (LayoutKind.Sequential)]
public struct STRUCT1 {
[MarshalAs( UnmanagedType.ByValArray,
ArraySubType=UnmanagedType.AnsiBStr, SizeConst=10 )]
byte[] field1;
[MarshalAs( UnmanagedType.ByValArray,
ArraySubType=UnmanagedType.AnsiBStr, SizeConst=10 )]
byte[] field2;
...
}

But I'm calling managed code from unmanaged code. And I don't know how to
define this struct so that this C# function declaration:

public unsafe void MyFunc(STRUCT1* p1, STRUCT2* p2)

doesn't make the compiler produce this error:

error CS0208: Cannot take the address or size of a variable of a
managed
type.

How can I mark the declaration of the struct so that the compiler knows
that
I want it to be unmanaged?

I know that I can just create a byte array that's the size of my struct,
pass pointers to the array into my code, and then use offsets to update
the
data in the array, but it seems really dumb to do thsat if there's another
way. Is there another way?

And, of course, is my conception of this problem all wrong?

Thanks in advance.

Bob Rossney
(e-mail address removed)
 
M

Mattias Sjögren

Robert,
[MarshalAs( UnmanagedType.ByValArray,
ArraySubType=UnmanagedType.AnsiBStr, SizeConst=10 )]
byte[] field1;

AnsiBStr isn't a valid subtype for ByValArray. Just remove the
ArraySubType assignment.

public unsafe void MyFunc(STRUCT1* p1, STRUCT2* p2)

Try changing the signature to

public void MyFunc(ref STRUCT1 p1, ref STRUCT2 p2)



Mattias
 

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