[使用C#在结构内使用不安全的固定大小的结构数组访问旧版C-dll

问题描述 投票:1回答:1

我有一个旧版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或可行的解决方法?

非常感谢!

c# arrays structure fixed
1个回答
0
投票

根据documentation for fixed sized buffers,无法在其中使用结构。

最好的选择似乎已经完成,并声明了1..n个字段。 this related question的答案暗示了同样的事情。如果问题仅仅是无法遍历字段,则考虑添加迭代器块,例如:

public IEnumerable<struc_RESULT_FORMULA> GetResultFormulas(){
    yield return oFormula01;
    ...
    yield return oFormula32;
}

如果需要随机索引,则可以选择大型switch语句/表达式。

© www.soinside.com 2019 - 2024. All rights reserved.