Я пытаюсь сделать старую 32-битную DLL Delphi пригодной для использования из моих приложений на C #. Использование суррогата системной DLL по умолчанию (dllhost.exe) представляется наиболее удобным решением.
Чтобы доказать, что это будет работать, я создал минимальную 32-битную тестовую DLL с Delphi, которая просто реализует один интерфейс с одним методом
HRESULT Add(double a, double b, double* c);
В моей тестовой программе на C # я сначала использовал внутрипроцессную активацию, которая сработала. Но поскольку мы хотим преодолеть 32/64-битный барьер, мы должны использовать DLL Surrogate. Поэтому я добавил необходимые записи реестра (AppID и т. Д.), Чтобы сделать эту работу, но все еще держал оба модуля (тестовый проект DLL и C #) на данный момент 32-битными.
Чтобы убедиться, что DLL не загружена в процессе, я 'вызвал' CoCreateInstance и использовал его так:
var adapter = CoCreateInstance(
new Guid("96810C5C-BA59-49D4-9732-EF902B8EFA72"),
null,
CLSCTX.CLSCTX_LOCAL_SERVER,
new Guid("00000000-0000-0000-C000-000000000046"));
Последний GUID - IUnknown, поэтому я даже не использую свой пользовательский интерфейс для этого теста (конечно, я начал с моего пользовательского интерфейса).
Проблема в том, что этот код уже не работает с:
0x8007065E "Data of this type not supported"
и я понятия не имею, о каких данных идет речь. Я подумал, что, возможно, будут поддерживаться только типы VARIANT, поэтому я изменил свою подпись на следующую и для теста даже пропустил параметр 'out':
HRESULT Add(VARIANT a, VARIANT b);
Все та же ошибка!
Есть идеи, что здесь не так?
Обновление 1
Объявление CoCreateInstance это
[Flags]
enum CLSCTX : uint
{
CLSCTX_INPROC_SERVER = 0x1,
CLSCTX_INPROC_HANDLER = 0x2,
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_INPROC_SERVER16 = 0x8,
CLSCTX_REMOTE_SERVER = 0x10
}
[DllImport("ole32.dll", ExactSpelling = true, PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
static extern object CoCreateInstance(
[In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
CLSCTX dwClsContext,
[In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
Обновление 2
Для полноты следует отметить, что в Delphi интерфейс разработан с помощью редактора библиотеки типов Delphi. Затем в C # я импортирую COM-объект как ссылку, которая, afaik, создает оболочку из библиотеки типов.
Обновление 3
Я только что реализовал тот же тестовый объект COM с C # и сделал его видимым для COM. Я даже не импортировал библиотеку типов для создания оболочки-оболочки, которую можно вызвать во время выполнения, а только пытался получить IUnknown с CoCreateInstance. То же сообщение об ошибке!
(Кстати, мой тестовый компьютер работает под управлением Windows 10)
Обновление 4
Я переписал клиента в Delphi и создал экземпляры обеих реализаций COM-объектов (Delphi и C #) с помощью суррогата DLL. То же сообщение об ошибке от CoCreateInstance!