Как передать байтовый массив из Delphi в C # DLL? - PullRequest
2 голосов
/ 20 сентября 2011

В c # есть dll с методом, который принимает байтовый массив.

public void CheckImageForFedCompliant(byte[] image)
 { 
       LoadImage(image);

        if (_errorMessages == null)
        {
            _errorMessages = new List<String>();
        }
        _errorMessages.Clear();

        // The image did not match the tiff specification so do not try to perform other tests. 
        if (!_tiffReader.IsTiff)
        {
            _errorMessages.Add("does not match the tiff specification");
        }

        if (!_tiffReader.IsSingleStrip)
            _errorMessages.Add("is not single strip");

        if (!_tiffReader.IsSinglePage)
            _errorMessages.Add("contains more than one page");


        TestCompression();
        TestPhotometricValue();
        TestImageWidthIsValidAndPresent();
        TestImageLengthIsValidAndPresent();
        TestXandYResolutionIsValidAndPresent();
        TestResolutionUnitIsValidPresent();
        TestStripByteCountsIsPresent();
        TestStripOffsetsIsPresent();
        TestRowsPerStripIsValidAndPresent();
        TestNewSubfileTypeIsValidAndPresent();
        TestBitPerSampleIsValidAndPresent();
        TestThresholdingIsValidAndPresent();
        TestFillOrderIsValidAndPresent();
        TestOrientationIsPresent();
        TestSamplePerPixelIsValidAndPresent();
        TestT6OptionsIsValidAndPresent();

    }
 }

Этот Dll, который я использую в Delphi (зарегистрирован и способен успешно вызывать метод dll).Функция delphi, имеющая указатель и размер изображения.Я вычисляю эти два, чтобы получить байтовый массив, но когда я передаю его, получаю ошибку вроде «Параметр неверен»

Function TscImage.Validate (pImagePointer : Pointer; dwImageSize : Cardinal) : Boolean;
var
  ImageByteArray      : array of byte;
begin
   SetLength(ImageByteArray, dwImageSize);
   Move(pImagePointer^, ImageByteArray, dwImageSize);  
   eFedImageCompliantResult := ImagingCommonIntrop.CheckImageForFedCompliant(ImageByteArray[0]);
   //  eFedImageCompliantResult := ImagingCommonIntrop.CheckImageForFedCompliant(ImageByteArray); internal error E6724
   Result := true;
end;

Может кто-нибудь поделиться какой-нибудь информацией по этому поводу?Или любое предложение.

1 Ответ

0 голосов
/ 11 апреля 2014

У меня были похожие проблемы при передаче разных видов массивов из C # в неуправляемый код Delphi / C / C ++ через COM / OLE интерфейс.

Вот что я нашелработает:

IDL file definitions:

[
  uuid(270FB76B-8CA7-47CA-AAA-7C76F55F39A2), 
  version(1.0), 
  helpstring("Interface for Logic Object"), 
  oleautomation
]
 interface ILogic: IUnknown
{
  [
  id(0x00000065)
  ]
  HRESULT _stdcall Sample1([in] double value, [in, out] int * length, [in, out] VARIANT * bytes );
  [
  id(0x00000066)
  ]
  HRESULT _stdcall Sample2([in, out] SAFEARRAY(double) array );
  [
  id(0x00000067)
  ]
  HRESULT _stdcall Echo([in] LPWSTR input, [in, out] LPWSTR * ouput );
};

Самый простой способ, используя VARIANT :

, он работает с любыми типами, такими как int, double и т. д.

Код Delphi:

function TLogic.Sample1(value: Double; var length: SYSINT;
  var bytes: OleVariant): HResult; stdcall;  
  var test: Byte;
begin  
    Result := 1;
    test := 7;

    for i := 0 to length do
      bytes[i] := test;
    end;    
end;

После regsrv32.exe name-of-lib.dll и добавления библиотеки COM к ссылкам с использованием Visual Studio

C # код:

ILogic test = new IClassLogic(); //COM inctance of interface (counter-intuitive for C#)
byte[] bytes = new byte[100000];
object obj = (object)bytes;
test.Sample1(2.0, ref length, ref obj);

Более сложный способ с использованием SAFEARRAY (кажется, не работает с байтом, но хорошо работает с другими типами данных):

SAFEARRAY (байт) => C # Массив не будет работать

SAFEARRAY (short) => C # Массив short

SAFEARRAY (long) => C # Массив int

SAFEARRAY (double) => C # Массив double

Код Delphi:

function TChromswordLogic.Sample2(var array: OleVariant): HResult; stdcall;  
  var test: Double;
begin  
    Result := 1;
    test := 7;

    SafeArrayLock(array);
  try
    for i := 0 to 9 do
    begin
        //SafeArrayGutElement(array, i);
        SafeArrayPutElement(array, i, test);     
    end;
  finally
    SafeArrayUnlock(array);
  end;   
end;

Код C #:

Array array = Array.CreateInstance(typeof(double), 10);
for (int i = array.GetLowerBound(0); i <= array.GetUpperBound(0); i++)
{
    double val = 2.2;
    array.SetValue(val, i);
}
test.Sample2(ref array);

Как, например, Echo выглядит следующим образом в C #:

void Echo(string input, ref string ouput)
...