tags:

views:

57

answers:

5

I have a method defined in an unmanaged DLL:

int foo(somestruct * vector, int size)

How can I call this method from C#? I've tried with MarshalAs Unmanaged.LPArray with no success. Am I required to use IntPtr and manually serialize into a List or similar.

I can't for the life of me find documentation on this on MSDN.

Essentially, I can't figure out how to complete the following snippet in my code:

[StructLayout(LayoutKind.Sequential), Serializable]
public struct somestruct
{
    //Whatever.
};

[DLLImport("some.dll")]
public static extern int foo( ???? );

Thanks.

+2  A: 

Have a look at DllImport attribute:

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx

This is exactly what you need.

This tutorial: http://msdn.microsoft.com/en-us/library/hk9wyw21.aspx might be specifically on your problem.

One more link on the problem: http://msdn.microsoft.com/en-us/library/z6cfh6e6.aspx#cpcondefaultmarshalingforarraysanchor2

Vlad
This is what I am trying to do. Perhaps I should clarify the question.
eckesicle
@Vlad - since eckesicle wrote that "MarshalAs Unmanaged.LPArray" did not work as expected I assume that the usage of `DllImport` is not the issue here.
Lucero
maybe this http://msdn.microsoft.com/en-us/library/hk9wyw21.aspx will be more helpful?
Vlad
That did it. Thanks.
eckesicle
A: 

LPArray should be correct.

Is the definition of somestruct correct? Is your C int 32 bits, or do you maybe have a mismatch there?

Maybe post the definition you tried also in the question, this may clarify things.

Lucero
Thanks, updated the question.
eckesicle
A: 

Yes, as far as I know you have to marshal that array manually using IntPtr. There was a question like this not long ago, check it out here. The other approach is to rewrite you native code into managed-C++ or create a C++-wrapper which calls the DLL for you.

Martin Wickman
A: 

.NET interop has no problem with struct as well as unmanaged array. You can define struct in C# and tell it to layout sequentially through custom attribute so it can map to you C struct. For array, you can use LPArray or even IntPtr and marshalling it yourself. You will need to use DllImport attribute to annotate the Dll method that you want to call in unmanaged code.

One other thing that is not obvious from your source code is the actualy C method. Have you declared it correctly as API export interface using __declspec (dllexport) ? and if you are compiling/coding it in C++ environment, then you should also include extern "C" in the beginning to make sure that the api interface is expose in the DLL correctly using C linking (naming convention) to prevent name decoration by C++ compiler.

Fadrian Sudaman
+2  A: 

It's much simpler than you think.

[DLLImport("some.dll")]
public static extern int foo(somestruct[] vector, int size);

The one thing to consider is marshaling direction. The runtime makes some decisions on whether to marshal the array before the call, after the call, or both. To make sure it makes the right decision, you may want to use In and/or Out attributes.

[DLLImport("some.dll")]
public static extern int foo([In] somestruct[] vector, int size);
// will only marshal the array to native memory before the call

[DLLImport("some.dll")]
public static extern int foo([Out] somestruct[] vector, int size);
// will only marshal the array to managed memory after the call

[DLLImport("some.dll")]
public static extern int foo([In, Out] somestruct[] vector, int size);
// will marshal the array both ways

On the other hand, if somestruct is blittable, then no marshaling is necessary, as the runtime can just pin the array and pass a pointer to the managed copy.

P Daddy