问题
I have been given a DLL ("InfoLookup.dll") that internally allocates structures and returns pointers to them from a lookup function. The structures contain string pointers:
extern "C"
{
struct Info
{
int id;
char* szName;
};
Info* LookupInfo( int id );
}
In C#, how can I declare the structure layout, declare the Interop call, and (assuming a non-null value is returned) utilize the string value? In other words, how do I translate the following into C#?
#include "InfoLookup.h"
void foo()
{
Info* info = LookupInfo( 0 );
if( info != 0 && info->szName != 0 )
DoSomethingWith( info->szName );
// NOTE: no cleanup here, the DLL is caching the lookup table internally
}
回答1:
Try the following layout. Code automatically generated using the PInvoke Interop Assistant. Hand coded LookpInfoWrapper()
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct Info {
/// int
public int id;
/// char*
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string szName;
}
public partial class NativeMethods {
/// Return Type: Info*
///id: int
[System.Runtime.InteropServices.DllImportAttribute("InfoLookup.dll", EntryPoint="LookupInfo")]
public static extern System.IntPtr LookupInfo(int id) ;
public static LoopInfoWrapper(int id) {
IntPtr ptr = LookupInfo(id);
return (Info)(Marshal.PtrToStructure(ptr, typeof(Info));
}
}
回答2:
For an example, see this netapi32.NetShareAdd interop declaration. It includes a SHARE_INFO_502
structure, with a public string shi502_netname
member. Many more examples are available at Pinvoke.net.
回答3:
Use Marshalling:
http://www.csharphelp.com/archives/archive63.html
回答4:
You need to implement the structure in C# as well, making sure to use the attributes in the Marshal class properly to ensure that the memory layout matches the unmanaged version.
So, some variation of this:
using System.Runtime.InteropServices;
[DllImport("mydll.dll")]
public static extern Info LookupInfo(int val);
[StructLayout(LayoutKind.Sequential)]
struct Info
{
int id;
String szName;
}
private void SomeFunction
{
Info info = LookupInfo(0);
//Note here that the returned struct cannot be null, so check the ID instead
if (info.id != 0 && !String.IsNullOrEmpty(info.szName))
DoSomethingWith(info.szName);
}
来源:https://stackoverflow.com/questions/356851/in-c-how-do-i-invoke-a-dll-function-that-returns-an-unmanaged-structure-contai