Вот задачка с которой я столкнулся несколько дней назад, исследовал массу сайтов, понял, что достаточно много людей не могут найти решение этой проблемы. Но теплется надежда, что все же есть человек, уже решивший ее.
Есть DLL-библиотека на C# (писана в Visual Studio .NET). Мне ее нужно использовать в Delphi 7.
Вся проблема в том, что у DLL, сделанной на C#, свои функции нельзя экспортировать. Как я понял, господа из Microsoft посчитали, что достаточно будет, если DLL-библиотека будет экспортировать целиком класс.
Куча работы на смарку (моей и 2 других людей) и все из-за того, что в DLL на C# нельзя экспортировать функции.
Может кто знает, как обойти эту нелепость?
Вы нас сильно выручите.
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
10-11-2006 02:47 | Комментарий к предыдущим ответам
ЗдОрово, все довольно понятно. То есть действительно это особенность (в общем-то преимущество) Дельфи, отсутствующая в C#. И применение по-моему актуальное. Я тоже думал о том, что в .NET реализовано много полезных вещей, которые можно было бы использовать в win32 программах. Но тут возникает проблема, что на компьютере должен быть .NET runtime. :(
DRON, cпасибо за ссылку.
09-10-2006 01:52 | Комментарий к предыдущим ответам
Аа, увидел, как можно обойтись без COM, во второй ссылке, которую приводил DRON, сразу просмотрел статью мельком и не заметил. Возможно, что Дельфи именно это и делает. (?)
02-10-2006 10:21 | Комментарий к предыдущим ответам
Я думаю Delphi генерирует традиционную Win32 библиотек. Просто если при загрузки библиотеки среда .Net Framework не загружена библиотека её подгружает и выполняет код в среде .Net Framework.
Вот это несколько и странно. Ведь вызвать какой-то .NET код из библиотеки должно быть примерно так же легко/сложно, как из приложения. Но известно, что из win32 приложения просто так это не сделаешь (если не ошибаюсь). Во всяком случае в справке .NET SDK я нашел только способ вызова через COM.
02-10-2006 07:35 | Комментарий к предыдущим ответам
>>>что генерирует в последнем случае Delphi - традиционную библиотеку для win32 или все-таки сборку .NET
Я думаю Delphi генерирует традиционную Win32 библиотек. Просто если при загрузки библиотеки среда .Net Framework не загружена библиотека её подгружает и выполняет код в среде .Net Framework.
Я пробывал подключить такую библиотеку в .Net приложение как пакет, но ни чего не вышло говорит нет мета данных, так что получилось работать только как с Win32 библиотекой. Но из .Net приложения работать с такой библиотекой лучше, нет проблем с SysUtils и Classes, и дебагер используется один, по этому можно дебажить как приложение так и библиотеку.
Интересно, а что генерирует в последнем случае Delphi - традиционную библиотеку для win32 или все-таки сборку .NET? В вашем случае возникает вопрос: если создается обычная библиотека, то как она в свою очередь вызывает код из библиотеки на C#. Ведь, чтобы вызвать библиотеку C# все равно должна запуститься .NET runtime, произойти Jit компиляция и т.д.
Кстати говоря, для экспорта класса C# в COM нужно описать интерфейс, соответствующий экспортируемым методам, к классу добавить атрибут
[ClassInterface(ClassInterfaceType.AutoDual)]
и в свойствах сборки указать [assembly: ComVisible(true)]
. Экспортируется с помощью утилиты regasm (windows\microsoft.ner\framework\номерверсии\)
Вроде бы примерно все, и еще сам файл библиотеки должен лежать в папке программы клиента или в папке, где хранятся все сборки (не помню точно путь)
Спасибо всем, кто откликнулся.
В особенности, хочу поблагодарить Марата Сафина и DRON'а. В который раз убеждаюсь, что Коллективный Разум способен творить чудеса.
Господа, для того чтобы вызвать из приложения на Delphi7 библиотеку на Delphi for .Net нужно:
1. Вызывать ее из Delphi 7 с параметром stdcall.
В самой DLL:
1. Убрать из Uses юниты SysUtils и Classes (почему не знаю, может кто объяснит нам всем?)
2. Добавить в начало юнита {$UNSAFECODE ON}
3. В конце же добавить секцию Exports.
TO DRON
1) За 2 статьи спасибо. В статье Inverse P/Invoke, как раз ребята и говорят, о том, что вызов процедур DLL на .NET из приложений на Win32 - настоящий кошмар.
2) Если поставить stdcall в .NET DLL, то ругается компилятор. Если добавить stdcall (а пробывал я также и safecall, register и даже cdecl), то эффект нулевой - также виснет.
Сейчас я работаю в направлении использовании COM'a напрямую без посредничества .NET DLL, но первые попытки тоже показывают, что там имеются подводные камни. (COM ведь писан вообще на C#, и несмотря на заверения господ из MS, думаю, там тоже подложена неодна свинья :-))
Буду держать Вас в курсе событий, если у кого появятся еще идеи - буду рад их выслушать.
Первое что у меня вызывает сомнения, это то что используются типы вызовов "по умолчанию", а я не думаю что они будут совпадать для NET и Win32 приложений. Может stdcall поставить или NET на него будет ругаться (не на чем сейчас проверить)?
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion('1.0.*')]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile('mykey.snk')], provided your output
// directory is the project directory (the default).
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile('')]
[assembly: AssemblyKeyName('')]
//
// Use the attributes below to control the COM visibility of your assembly. By
// default the entire assembly is visible to COM. Setting ComVisible to false
// is the recommended default for your assembly. To then expose a class and interface
// to COM set ComVisible to true on each one. It is also recommended to add a
// Guid attribute.
//
22-09-2006 04:54 | Комментарий к предыдущим ответам
>>>моя программа вздохнула и глухо подвисла.
Если после прочтения ссылок которые дал DRON у вас всё ещё не будет получатся експортировать функции из Delphi for .Net то прошу код на сцену, наверника ошибка там.
TO Марат Сафин:
Марат, в общем, я уже попробывал так сделать. Расскажу, что из этого вышло. Я написал DLL на Delphi for .NET. Дальше добавил Exports. Меня выругали. :-) Тогда я лобавил что-то вроде {UNSAFECODE ON} в начало юнита и компилятор промолчал на Exports. НО! Когда я подцепил получившееся чудо природы к Exe в Дельфи 7, то моя программа вздохнула и глухо подвисла. :-(
TO al_mt:
Логичный комментарий, если бы не все прелести архитектуры. Разрабатываем приложение для Лотус. Там Длл должна быть именно на C, ведь Lotus C API именно на Си. А интерфейс пишется на C#, т.к. есть куча наработок. Вот и вся песня.
TO Сергей Осколков:
У меня тоже в голове вертится мысль о COM, тем более, что DLL на C# как раз и взаимодействует с COM (писан тоже на C#). Изначально я даже пытался подключиться к COM напрямую, но, видимо, там тоже есть свои нюансы. Я обязательно посмотрю Exposing .NET Framework Components to COM.
Интересно, а может у кто-нибудь из жителей королевства уже есть опыт использования COM объектов, разработанных на C#, в проектах на Delphi или С, С++ (но без использования Framework'a .NET)
Я думаю, что можно это сделать через COM, если это устраивает. Посмотрите в .NET framework SDK раздел "Programming with the .NET Framework" -> Interoperating with Unmanaged Code -> Exposing .NET Framework Components to COM.
Интересно только нафига писать на C# библиотеку для Delphi 7 ?!
Потому-что в c# думать меньше надо, за вас уже всё продумали ребята из Microsoft! Да взять эти назойливые визарды... Хорошо оставили возможность создавать всё руками, но думаю скоро и этого удовольствия нас лишат. :'(
В Delphi for .Net можно писать Library которые експортируют функции как обычные DLL. Сам не пробывал но в книгах так написано. Можно написать промежуточную DLL на Delphi for .Net которая будет обращатся к .Net библиотеке и экспортировать нужные функции или библиотеку на C# переписать под Delphi for .Net.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.