передача tStringList в C # в Delphi DLL - PullRequest
       226

передача tStringList в C # в Delphi DLL

2 голосов
/ 30 сентября 2008

У меня есть Delphi DLL с функцией, определенной как:

функция SubmitJobStringList (список заданий: tStringList; переменная jobno: целое число): целое число;

Я звоню из C #. Как мне объявить первый параметр как tStringList не существует в C #. В настоящее время у меня есть объявление как:

[DllImport("opt7bja.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int SubmitJobStringList(string[] tStringList, ref int jobno);

Но когда я звоню, я получаю исключение нарушения доступа к памяти.

Кто-нибудь знает, как правильно перейти к tStringList из C #?

Ответы [ 7 ]

13 голосов
/ 30 сентября 2008

Скорее всего, вам не повезет. TStringList - это не просто массив, это полноценный класс, и точные детали реализации могут отличаться от того, что возможно в .NET. Взгляните на исходный код Delphi VCL (то есть, если он у вас есть) и попытайтесь выяснить, можете ли вы перестроить класс в C #, и передайте его с помощью своего лучшего друга, Interop Marshaller. Обратите внимание, что даже тип строки Delphi отличается от типа строки .NET, и, передавая его без указания маршаллеру, что он должен делать, он, скорее всего, передаст его как массив символов.

Кроме этого, я бы предложил изменить DLL-библиотеку Delphi. Никогда не стоит выставлять что-то специфичное для Delphi в DLL, которая будет использоваться не-Delphi-клиентами. Сделайте параметр массивом PChar, и все будет в порядке.

2 голосов
/ 30 сентября 2008

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

Или, если вы действительно хотите по какой-то причине использовать TStringList, Delphi VCL.Net можно использовать с любого языка .Net.

Старый пример с использованием TIniFile: http://cc.codegear.com/Item/22691

В примере используется .Net 1.1 в Delphi 2005. Delphi 2006 и 2007 поддерживают .Net 2.0.

1 голос
/ 30 сентября 2008

Если вы не управляете библиотекой DLL, а они не могут или не захотят ее изменить, вы всегда можете написать свою собственную оболочку Delphi в отдельной библиотеке DLL с параметрами, более удобными для разных языков.

Наличие класса в качестве параметра функции DLL действительно является плохим тоном.

0 голосов
/ 01 октября 2008

Я мало что знаю о c #, но метод, который я использую для переноса списков строк через контексты, - это использование свойства .text для получения строки, представляющей список, а затем присвоение этого свойства «на другой стороне».

Как правило, легче натянуть на стену веревку, чтобы она была полноценным объектом.

0 голосов
/ 30 сентября 2008

Как сказал Хемант Джангид, вы легко сможете сделать это, скомпилировав свой код в виде .NET dll, а затем сославшись на эту сборку в своем проекте на c #.

Конечно, вы сможете сделать это только в том случае, если у вас установлена ​​версия Delphi с Delphi.NET.

0 голосов
/ 30 сентября 2008

Теоретически, вы могли бы сделать что-то подобное, используя указатели (приводя их к типу C # IntPtr) вместо строго типизированных ссылок на объекты (или, возможно, заключая их в какой-то другой тип, чтобы избежать объявления небезопасные блоки), но основная проблема заключается в следующем: среда выполнения Delphi должна быть механизмом выделения и освобождения памяти для объектов. Для этого вы должны объявить функции в вашей скомпилированной Delphi DLL, которые вызывают конструкторы и деструкторы для класса TStringList, вы должны убедиться, что ваша Delphi DLL использует модуль ShareMem, и вы должны взять на себя ответственность за увеличение и уменьшение счетчика ссылок. для ваших Delphi AnsiStrings до того, как они покинут DLL, и после того, как они войдут в нее, предпочтительно также в виде функций, экспортированных из вашей Delphi DLL.

Короче говоря, это много работы, поскольку вы должны манипулировать двумя менеджерами памяти в одном и том же процессе (.NET CLR и распределители Delphi), и вы оба должны управлять памятью вручную и"Дурак" менеджер памяти Delphi и время выполнения. Есть ли конкретная причина, по которой вы связаны с этой настройкой? Не могли бы вы описать проблему, которую вы пытаетесь решить на более высоком уровне?

0 голосов
/ 30 сентября 2008

Мне не совсем понятен ваш способ использования delphi и C #. Кажется, вы создали Win32 DLL, которую хотите вызвать из C #. Конечно, вы должны использовать PInvoke для этого.

Я бы посоветовал вам создать .NET DLL с использованием вашего исходного кода, поскольку доступно полное портирование VCL Я могу уточнить, если вы хотите ....

...