C # вызывает Delphi DLL, которая возвращает структуру внутри структуры - PullRequest
2 голосов
/ 24 ноября 2011

Еще один вопрос о взаимодействии с Delphi ......

У меня есть этот код Delphi:

library DelphiDll;

uses
  Dialogs,
  SysUtils,
  Classes;

  type
    TestEnum = (teOne, teTwo);

    TTestRecord = record
    end;

    TTestType = record
      MyTestRecords: array [1..255] of TTestRecord;
      MyTestEnum: TestEnum;
    end;

  {$R *.res}

  function DllFunction(var testType: TTestType): Boolean stdcall; export;

  begin
    testType.MyTestEnum := teTwo;

    Result := True;
  end;

  exports DllFunction;

  begin
  end.

И этот код C #:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace DelpiDllTester
{
    public enum TestEnum
    {
        One,
        Two
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct TestType
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
        public TestRecord[] MyTestRecords;
        public TestEnum MyTestEnum;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct TestRecord
    {
    }

    class Program
    {
        [DllImport("DelphiDll.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
        public static extern bool DllFunction(ref TestType testType);

        static void Main(string[] args)
        {
            TestType testType = new TestType();
            bool dllFunctionResult = DllFunction(ref testType);

            Console.WriteLine(dllFunctionResult);
            Console.WriteLine(testType.MyTestEnum);

            Console.ReadLine();
        }
    }
}

Когда я запускаю код C #, вывод консоли для testType.MyTestEnum всегда равен значению enum One, хотя в коде Delphi для него явно установлено значение Two.

Теперь, если я просто перейду от использования массива структур TestRecord в структуре TestType к использованию простого массива целых чисел, все будет хорошо.

Почему массив целых чисел работает, а массив структур - нет?

Ответы [ 3 ]

3 голосов
/ 24 ноября 2011

Основная проблема заключается в том, что TTestRecord не имеет содержимого, определенного в нем. Код C # представляет это поле размером 1. Компилятор Delphi считает, что он имеет размер 0. И, следовательно, существует несоответствие между этими двумя структурами. Код C # возвращает 260 для Marshal.SizeOf(typeof(TestType)), тогда как компилятор Delphi возвращает 8 для SizeOf(TTestType).

В реальном коде, вероятно, будет какой-то фактический контент в этой записи, и когда вы это сделаете, все начнет работать.

Обратите внимание, что @JMarsch и @Ken White также дают правильные очки. Вам нужно будет убедиться, что перечисление правильно распределяется и что макеты struct совпадают. Из-за того, как структуры дополняются, вы можете уйти, ничего не делая со своим списком перечислений, но вы также можете быть невезучим!

2 голосов
/ 24 ноября 2011

Вам необходимо установить размер перечисления в вашем Delphi-коде.Delphi сделает его как можно меньше, но сторона .NET ожидает int.Добавьте следующее к своему коду перед объявлением перечисления:

{$MINENUMSIZE 4}   // can also use {$Z4} but it's not clear later when
                   // you're trying to maintain the code.
                   // Or you can use {$Z-} and {$Z+}, for
                   // {$Z1} and {$Z4} respectively

// Your enum declaration

{$MINENUMSIZE 1}
2 голосов
/ 24 ноября 2011

Это была совсем другая жизнь, так как я использовал Delphi (например, '98), но, как я помню, перечисления в Delphi были 1-байтовыми числами.Перечисления в c # являются целочисленными (32-разрядными).

Итак, вы можете попытаться определить свое перечисление c # как

enum TestEnum: byte {One, Two}

. Это не объясняет того, как он работает с массивом.инт.О единственной другой вещи, о которой я могу подумать, - это убедиться, что значения перечисления c # в точности совпадают со значениями перечисления Delphi (поэтому используйте teOne, teTwo), но поскольку мы действительно говорим о целом / байте под обложками,Я не понимаю, как это будет иметь значение.

...