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

2

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

function SubmitJobStringList (список заданий: tStringList; var jobno: Integer): Integer;

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

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

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

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

Теги:
dll
tstringlist

7 ответов

13
Лучший ответ

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

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

2

Если это ваша 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

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

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

0

Я не знаю много о С#, но метод, который я использую для переноса строковых списков в контекстах, использует свойство .text, чтобы получить строку, представляющую список, а затем присвоить это свойство "другой стороне".

Как правило, проще получить строку над стеной, которая является полномасштабным объектом.

0

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

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

0

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

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

0

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню