Dllimport не может импортировать старую dll Borland

У меня есть много устаревшего кода, который я в настоящее время компилирую, используя устаревшую установку Borland C++ 3.0.

В этом коде есть механизм правил, который я хотел бы извлечь и использовать в приложении C# .NET.

Дело в том, что если я извлеку механизм правил в его собственную DLL, я хочу иметь возможность вызывать эту DLL как из существующего устаревшего кода, который у меня нет времени портировать, так и из приложения C# .NET.

Если я соберу DLL с помощью старого компилятора Borland, я не смогу сообразить, как ссылаться на нее из проекта C# .Net. DllImport завершается с ошибкой BadImageFormatException. Поиск в Google этого исключения показывает, что большинство людей сталкиваются с этой проблемой при компиляции 64-битной программы и загрузке в нее чего-то 32-битного. Дело в том, что я достаточно уверен, что генерирую 16-битные библиотеки DLL, и, похоже, для этого нет обходного пути.

Я могу загрузить более новый компилятор Borland 5 с 32-битным компилятором и компоновщиком, но у меня все еще возникает та же проблема, так что, возможно, у меня тоже что-то не так.

Это мой код вызова С#

[DllImport( "C:\\NSDB\\BorlandDLL\\BorlandDLL.dll", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl )]
static extern int Version();

public frmHelpAbout()
{
    InitializeComponent();

    lblIssueVersion.Text =  + Version();
}

Это мой DLL-код

int Version()
{
    return 93;
}

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

Я заметил, что мой код DLL не украшен ничем вроде __stdcall, extern "C" или чем-то еще. Кажется, я не могу найти правильный набор символов, понятный Borland C++ 3.0, для принудительного применения тех соглашений о вызовах, которые мне нужны.

Итак, вопросы:

1) Сможет ли когда-нибудь DllImport работать с кодом, сгенерированным из Borland C++ 3.0 1b) Если нет, смогу ли я портировать код для работы с компилятором Borland C+ 5.5.1 и заставить DllImport работать с ним?

2) Можно ли решить проблему? Если бы я перенес код DLL в .NET, смог бы я когда-нибудь заставить старый код Borland вызывать его?

3) Есть ли у вас какие-либо другие инновационные решения, которые позволят мне просто извлечь нужный мне код из этого старого проекта Borland?


person Paul Smith    schedule 24.09.2009    source источник


Ответы (3)


Насколько я знаю, DllImport будет работать только с неуправляемыми dll, которые имеют тот же размер слова, что и приложение .Net. Например. DllImport в 64-битном приложении .Net будет работать только с 64-битными dll, 32-битное .Net приложение может загружать только 32-битные dll и т. д. Я также не думаю, что возможно заставить DllImport загружать 16 -бит dll.

Некоторые возможные решения приходят на ум:

  1. Стив упомянул об использовании COM. Если вы хотите, чтобы ваше приложение .Net было 64-битным, вы можете использовать COM, чтобы все работало следующим образом: перекомпилируйте свой код C как 32-битную dll, используйте .Net для написания 32-битной оболочки COM для этой dll. , затем пусть ваше 64-битное приложение .Net вызовет 32-битный COM-сервер, который, в свою очередь, вызовет вашу 32-битную dll. В MSDN есть некоторая информация о взаимодействии с неуправляемым кодом.

  2. Скомпилируйте свою dll и приложение .Net для 32-битной версии. Тогда DllImport сможет загрузить dll. (Возможно, вам придется обернуть код C в extern "C" и запустить утилиты TDUMP или DUMPBIN в dll, чтобы проверить искажение имен).

  3. Если у вас есть весь исходный код C, можете ли вы просто забыть о компиляторе Borland и построить код с помощью компилятора Visual Studio C++?

person Chris R. Timmons    schedule 24.09.2009
comment
Я не думаю, что смогу сделать 3 — пока мне нужно, чтобы существующая программа работала так, как она есть, и она использует библиотеки пользовательского интерфейса Borland для консоли. У меня есть код, который я сопоставляю с Borland: extern C int __declspec(dllexport) _stdcall DoAdd(int i, int j) { return i+j; } Даже при компиляции с помощью bcc32 (который, как я полагаю, является 32-разрядным компилятором!) и компоновке с помощью ilink32, я все еще не могу получить загружаемую DLL. Как узнать, действительно ли сгенерированная DLL является 32-битной? - person Paul Smith; 24.09.2009
comment
Должно быть, у меня что-то не так в настройках компилятора. Использование bcc32 с параметром -WD создает загружаемую DLL. - person Paul Smith; 24.09.2009

.net будет вызывать COM и вполне может вызываться как COM (для подходящего COM-скорректированного значения happy), поэтому, если старый нативный код предоставляет подходящий COM-интерфейс, вы можете попробовать использовать его напрямую (но для этого нужно будет использовать 32-битная сборка).

Если вам не нужно, чтобы все было в одном процессе, альтернативным подходом может быть сборка кода в виде сборки C++/CLI и в виде библиотеки DLL Borland (если у вас есть .c файлов, вам понадобятся .cpp файлов, которые просто #include файл .c в проекте .net).

person Steve Gilham    schedule 24.09.2009
comment
Извините, я действительно не понимаю вашего сообщения. Старый код — это просто приложение C. Он не разбит на библиотеки или что-то в этом роде - он, конечно, не предоставляет COM-интерфейс. Я хочу извлечь полезную часть этого кода и оставить весь код пользовательского интерфейса. Я должен вызывать обработчик правил из нового кода C#, и я все еще должен вызывать обработчик правил из старого старого кода Borland. Должен ли я углубиться в COM (я никогда не понимал COM, хотя часто видел аббревиатуру)? С чего начать? Мне нравится идея иметь код, который строится под любым компилятором, но это звучит непросто... - person Paul Smith; 24.09.2009

Если вы используете как 32-битную .NET, так и 32-битную C-DLL, у вас не должно возникнуть проблем. Я почти на 100% уверен, что вы не сможете легко вызвать 16-битный код из 32-битного приложения (хотя я думаю, что видел решения, которые делают это - здесь мне приходит на ум слово "thunking"?).

Если и .NET, и DLL являются 32-битными, вы должны быть в порядке с тем, что вы делаете выше, но я помню, что в DLL Borland было что-то, что делало их несовместимыми с другими «обычными» C-DLL.

Я думаю, что ответ Стива Гилхэма о COM можно игнорировать, поскольку COM не является ни необходимым, ни хорошим вариантом в вашем случае.

person Thorsten Dittmar    schedule 24.09.2009