简体   繁体   English

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

[英]Access legacy C-dll with C# using unsafe fixed size array of struct within struct

I have a legacy C-dll to access a Hardware Device.我有一个旧的 C-dll 来访问硬件设备。 The dll uses structures containing structure Arrays as function arguments. And I am having a hard time to get this working together with C# (in unsafe mode which is ok since access Speed is an issue here). dll 使用包含结构 Arrays 的结构作为 function arguments。我很难让它与 C# 一起工作(在不安全模式下,这是可以的,因为访问速度是这里的一个问题)。

The original declaration from DeviceDll.h of the legacy C-dll Looks like:来自旧版 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[]);

Declaring the C-dll functions in C# is done in the following way:在 C# 中声明 C-dll 函数是通过以下方式完成的:

[DllImport("ExternalDevice.dll")]   
public unsafe static extern int GetResult(StringBuilder pDeviceCode, struc_RESULT_SCRIPT_NO_LIST* pList, struc_RESULT_SCRIPT **ppResult);

and the structure which I want to access I have declared in a way which unfortunatly gives an error:以及我想要访问的结构我以一种不幸的方式声明了错误:

[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;
}

Error: Buffer of a fixed size must be of "bool", "Byte", .错误:固定大小的缓冲区必须是“bool”,“Byte”,。 . . . . or "double"或“双”

Is there a way to declare a fixed structure Array within a structure so that I can use a structure-type variable afterwards as an Argument for calling the legacy DLL?有没有办法在结构中声明一个固定结构数组,以便我可以在之后使用结构类型变量作为调用遗留 DLL 的参数?

What I have tried so far:到目前为止我尝试了什么:

Avoiding a structure Array within a structure (rather clumsy but working)避免结构中的结构数组(相当笨拙但有效)

    [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;

This is working - but accessing oFormula01 … oFormula32 for 32 structure-variables is rather clumsy.这是有效的 - 但访问 oFormula01 … oFormula32 的 32 个结构变量相当笨拙。 I would strongly prefer to get the result as an Array so that I can Access it like oFormula = arrayFormula[xx];我非常希望将结果作为数组获取,这样我就可以像 oFormula = arrayFormula[xx]; 一样访问它。 within a for - loop.在 for - 循环中。

Is there a way to declare an unsafe, fixed structure Array within a structure in C# - or a feasable work-around?有没有办法在 C# 的结构中声明一个不安全的固定结构数组 - 或者一个可行的解决方法?

Thank you very much in advance!非常感谢您!

According to the documentation for fixed sized buffers there is no way use structs in them.根据固定大小缓冲区的文档,无法在其中使用结构。

The best option seem to do as you have done and declare 1..n fields.最好的选择似乎是按照你所做的那样做并声明 1..n 字段。 The anwer to this related question suggest the same thing.这个相关问题的答案暗示了同样的事情。 If the problem is simply not being able to loop over the fields, then consider adding a iterator block, like:如果问题只是无法遍历字段,请考虑添加一个迭代器块,例如:

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

An alternative would be a large switch statement/expression if you need random indexing.如果您需要随机索引,另一种方法是使用大型 switch 语句/表达式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM