我必须从C#调用一个非托管函数,并且必须为它提供一个坐标数组(双精度数)。编组如何正确地处理此案例?
在非管理方面:
typedef struct dPoint3dTag
{
double x, y, z;
} dPoint3d;
void UnmanagedModifyGeometry(char *strFeaId, dPoint3d *pnts, int iNumPnts);
我在管理端为DPoint3d定义了托管结构:
[StructLayout(LayoutKind.Sequential)]
public struct DPoint3d
{
// Constructor
public DPoint3d(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
public double x, y, z;
}
我试图以这种方式从C#调用非托管函数:
// Import of the unmanaged function
[DllImport("Unmanaged.dll")]
public static extern void UnmanagedModifyGeometry([MarshalAs(UnmanagedType.LPStr)] string strFeaId, DPoint3d[] pnts, int iNumPnts);
// Using the unmanaged function from C#
// Allocating points
DPoint3d[] pnts = new DPoint3d[iPntCnt];
String strFeaId = "4711";
// After filling in the points call the unmanaged function
UnmanagedModifyGeometry(strFeaId, pnts, iPntCnt);
此工作流程是否正确?
此致 tomtorell
答案 0 :(得分:1)
首先,在非托管方面,char*
是一个可修改的字符串。您应该在此处使用const
来指示数据从调用者流向被调用者。对其他参数做同样的事情是有道理的:
void UnmanagedModifyGeometry(
const char *strFeaId,
const dPoint3d *pnts,
const int iNumPnts
);
现在很清楚所有数据如何流动。
在管理方面,声明存在一个明显的问题,即您没有指定调用约定。默认值是stdcall,但是你的非托管代码将是cdecl,假设问题中的声明是准确的。
您显示的结构声明完全匹配。关于这个问题没有什么可说的。
您还可以使用默认编组来简化p / invoke。我这样写:
[DllImport("Unmanaged.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void UnmanagedModifyGeometry(
string strFeaId,
[In] DPoint3d[] pnts,
int iNumPnts
);
并称之为:
DPoint3d[] pnts = new DPoint3d[...]; // supply appropriate value for array length
// populate pnts
UnmanagedModifyGeometry("4711", pnts, pnts.Length);