Получите доступ к устаревшей C -dll с помощью C#, используя небезопасный массив фиксированного размера struct внутри struct - PullRequest
1 голос
/ 14 апреля 2020

У меня есть устаревшая C -dll для доступа к аппаратному устройству. В качестве аргументов функции DLL использует структуры, содержащие структурные массивы. И мне тяжело заставить это работать вместе с C# (в небезопасном режиме, который в порядке, так как скорость доступа здесь является проблемой).

Исходное объявление из DeviceDll.h старой C -dll выглядит так:

    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 -dll в C# выполняется следующим образом. путь:

[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",. , , или "double"

Есть ли способ объявить фиксированную структуру Array в структуре, чтобы впоследствии я мог использовать переменную типа структуры в качестве аргумента для вызова устаревшей DLL?

Что Я пытался до сих пор:

Как избежать структуры Array в структуре (довольно неуклюже, но работает)

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

Это работает - но доступ к oFormula01… oFormula32 для 32 структурных переменных довольно неуклюжим. Я бы настоятельно предпочел получить результат в виде массива, чтобы я мог получить к нему доступ, например oFormula = arrayFormula [xx]; в течение for - l oop.

Есть ли способ объявить небезопасную фиксированную структуру Array в структуре в C# - или возможный обходной путь?

Спасибо очень заранее!

1 Ответ

0 голосов
/ 14 апреля 2020

В соответствии с документацией для буферов фиксированного размера нет никакой возможности использовать структуры в них.

Кажется, что лучший вариант сделать, как вы сделали, и объявить поля 1..n. Ответ на этот связанный вопрос предполагает то же самое. Если проблема заключается просто в невозможности l oop над полями, рассмотрите возможность добавления блока итератора, например:

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

Альтернативой может быть большой оператор / выражение switch, если вам нужна случайная индексация ,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...