我有一个旧版C-dll,可以访问硬件设备。 dll使用包含结构数组作为函数参数的结构。而且我很难将其与C#一起使用(在不安全的模式下也可以,因为在这里访问速度是一个问题)。
来自旧版C-dll的DeviceDll.h的原始声明看起来像:
typedef struct tag_RESULT_JUDGEMENT
{
short nJudgementResult;
} struc_RESULT_JUDGEMENT;
typedef struct tag_RESULT_FORMULA
{
float fFormulaResult[3];
float fAnalogResult;
} struc_RESULT_FORMULA;
typedef struct tag_RESULT_SCRIPT
{
short nScriptNo;
float fTime;
short nFormulaCount;
struc_RESULT_FORMULA sFormula[32];
short nJudgementCount;
struc_RESULT_JUDGEMENT sJudgement[8];
} struc_RESULT_SCRIPT;
WORD PASCAL GetResult(LPCTSTR pDeviceCode, struc_RESULT_SCRIPT_NO_LIST* pList, struc_RESULT_SCRIPT* pResult[]);
通过以下方式声明C#中的C-dll函数:
[DllImport("ExternalDevice.dll")]
public unsafe static extern int GetResult(StringBuilder pDeviceCode, struc_RESULT_SCRIPT_NO_LIST* pList, struc_RESULT_SCRIPT **ppResult);
以及我要访问的结构以一种不幸的方式给出了错误的方式声明:
[StructLayout(LayoutKind.Explicit)]
public unsafe struct struc_RESULT_SCRIPT {
[FieldOffset(0)]
public Int16 nScriptNo;
[FieldOffset(2)]
public float fTime;
[FieldOffset(6)]
public Int16 iFormulaCount;
[FieldOffset(8)
public fixed struc_RESULT_FORMULA[32] oFormula;
}
错误:固定大小的缓冲区必须为“ bool”,“ Byte”,“。 。 。或“双”
是否有一种方法可以在结构内声明固定结构的数组,以便以后可以使用结构类型变量作为调用旧版DLL的参数?
到目前为止我尝试过的:
避免在结构中使用结构数组(虽然笨拙但有效)
[StructLayout(LayoutKind.Explicit)]
public unsafe struct struc_RESULT_SCRIPT {
[FieldOffset(0)]
public Int16 nScriptNo;
[FieldOffset(2)]
public float fTime;
[FieldOffset(6)]
public Int16 iFormulaCount;
[FieldOffset(8)
public struc_RESULT_FORMULA oFormula01;
[FieldOffset(8 + 16)
public struc_RESULT_FORMULA oFormula02;
. . .
[FieldOffset(8 + 31*16)
public struc_RESULT_FORMULA oFormula32;
}
. . .
struc_RESULT_SCRIPT** ppResult; //local variable => allocated on the stack => so it's already fixed
. . .
int iRv = GetResult(sbMpmIp, &oScriptList, ppResult);
struc_RESULT_FORMULA oFormulaResult = ppResult[0]->oFormula01;
这是可行的-但是访问32个结构变量的oFormula01…oFormula32相当笨拙。我强烈希望将结果作为数组来获取,以便像oFormula = arrayFormula [xx];一样访问它。在for-循环中。
是否有一种方法可以在C#中的结构内声明不安全的固定结构Array或可行的解决方法?
非常感谢!
根据documentation for fixed sized buffers,无法在其中使用结构。
最好的选择似乎已经完成,并声明了1..n个字段。 this related question的答案暗示了同样的事情。如果问题仅仅是无法遍历字段,则考虑添加迭代器块,例如:
public IEnumerable<struc_RESULT_FORMULA> GetResultFormulas(){
yield return oFormula01;
...
yield return oFormula32;
}
如果需要随机索引,则可以选择大型switch语句/表达式。