Reputation:
I have a c++ dll which exposes the following function
long func(struct name * myname)
{
strcpy(myname->firstname,"rakesh");
strcpy(myname->lastname,"agarwal");
return S_OK;
}
struct name
{
char firstname[100];
char lastname[100];
}
I want to call this function from a C# application , so I do the following :
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
unsafe public struct name
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=100)]
public string firstname;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
public string lastname;
} ;
[DllImport("C++Dll.dll")]
public unsafe static extern long func(name[] myname);
name[] myname = new name[1];
func(myname);
The application builds successfully. When the C# application .exe is run, the function func()
is called successfully and it is able to populate the fields successfully inside the dll. But when the function returns to the C# application, the variable myname
still conatins null values for the struct fields(firstname
and lastname
).
Please suggest changes so that I am able to populate the fields values of myname
(so that after the function func()
finishes execution, the variable myname->firstname
contains "rakesh" and myname->lastname
contains "agarwal".
Note: StringBuilder cannot be used inside the structure.
Upvotes: 3
Views: 12616
Reputation: 754575
Instead of using an array, pass the struct by reference. For a PInvoke call, a ref struct will be translated into a pointer to the struct. The ref argument also tells the CLR to marshal data in both directions, to native code and then back out again.
[DllImport("C++Dll.dll")]
public unsafe static extern long func(ref name myname);
Also, if you're doing a lot of interop work I suggest you check out the PInvoke interop assistant (link). This tool will automatically convert the majority of C type definitions (including structs, enums, unions and function pointers) into their corresponding C# or VB.Net types. It will additionally convert signatures which contain these types.
Upvotes: 7
Reputation: 74802
Declare the import as public unsafe static extern long func(ref name myname)
, and call it as:
name myname = new name();
func(ref myname);
You probably don't need the unsafe declarations on the name structure or import declaration, by the way.
Upvotes: 3