Я в процессе создания плагина Heartrate Monitor для OBS Studio. Идея состоит в том, чтобы получить доступ к службам Bluetooth GATT на стороне C#, чтобы получить данные от Smart BT HRM, обработать их и затем передать их в C ++ dll, который действует как сам плагин OBS Studio.
Мне удалось чтобы все заработало, и я могу вызвать функцию на стороне C# из C ++, которая возвращает массив с данными изображения, который я впоследствии могу передать OBS. Однако для этого требуется, чтобы DLL-библиотека C# была зарегистрирована. Я бы предпочел не загрязнять реестр бесполезной информацией DLL, поэтому я заглянул в регистрацию Free COM. (Это также сделало бы распространение / установку много проще)
После долгих хлопот я зашел в тупик. С sxstrace я знаю, что параллельная система подбирает нужную библиотеку:
=================
Begin Activation Context Generation.
Input Parameter:
Flags = 0
ProcessorArchitecture = AMD64
CultureFallBacks = en-US;en
ManifestPath = C:\Program Files\obs-studio\obs-plugins\64bit\HrmPlugin.dll
AssemblyDirectory = C:\Program Files\obs-studio\obs-plugins\64bit\
Application Config File =
-----------------
INFO: Parsing Manifest File C:\Program Files\obs-studio\obs-plugins\64bit\HrmPlugin.dll.
INFO: Manifest Definition Identity is HrmPlugin,processorArchitecture="AMD64",type="win32",version="1.0.0.0".
INFO: Reference: OBSBluetoothHeartrate,processorArchitecture="*",type="win32",version="1.0.0.0"
INFO: Resolving reference OBSBluetoothHeartrate,processorArchitecture="*",type="win32",version="1.0.0.0".
INFO: Resolving reference for ProcessorArchitecture AMD64.
INFO: Resolving reference for culture Neutral.
INFO: Applying Binding Policy.
INFO: No binding policy redirect found.
INFO: Begin assembly probing.
INFO: Did not find the assembly in WinSxS.
INFO: Attempt to probe manifest at C:\Program Files\obs-studio\obs-plugins\64bit\OBSBluetoothHeartrate.DLL.
INFO: Manifest found at C:\Program Files\obs-studio\obs-plugins\64bit\OBSBluetoothHeartrate.DLL.
INFO: End assembly probing.
INFO: Resolving reference OBSBluetoothHeartrate.mui,language="*",processorArchitecture="AMD64",type="win32",version="1.0.0.0".
INFO: Resolving reference for ProcessorArchitecture AMD64.
INFO: Resolving reference for culture en-US.
INFO: Applying Binding Policy.
INFO: No binding policy redirect found.
INFO: Begin assembly probing.
INFO: Did not find the assembly in WinSxS.
INFO: Did not find manifest for culture en-US.
INFO: End assembly probing.
INFO: Resolving reference for culture en.
INFO: Applying Binding Policy.
INFO: No binding policy redirect found.
INFO: Begin assembly probing.
INFO: Did not find the assembly in WinSxS.
INFO: Did not find manifest for culture en.
INFO: End assembly probing.
INFO: Parsing Manifest File C:\Program Files\obs-studio\obs-plugins\64bit\OBSBluetoothHeartrate.DLL.
INFO: Manifest Definition Identity is OBSBluetoothHeartrate,processorArchitecture="AMD64",type="win32",version="1.0.0.0".
INFO: Activation Context generation succeeded.
End Activation Context Generation.
Однако, когда я пытаюсь создать класс из самого COM-объекта, я получаю класс, не найдена ошибка. Код для его создания выглядит следующим образом:
static void Initialize(hrm_source *context)
{
if (context->init_failed) return;
try
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
IHrmPluginPtr pHRM(CLSID_HrmPlugin);
context->pHRM = pHRM;
}
catch (_com_error _com_err)
{
MessageBox(NULL, _com_err.ErrorMessage(), L"Failed to initialize COM", MB_OK);
context->pHRM = NULL;
context->init_failed = (context->pHRM == NULL);
}
}
Проблема в том, что все это работает, если либо A) я регистрирую сборку, либо B) я использую из exe. На самом деле, если я изменяю тип вывода .exe, добавляю main () к plugin-dll-source и создаю его оттуда, я могу запустить exe, и он работает правильно.
| C++ Exe | C++ DLL
-------------------------------------
Registered | Works | Works
Register Free | Works | Doesn't Work
Там это, очевидно, какой-то флаг конфигурации (ну, скрестив пальцы) или параметр или атрибут, отсутствующий в файлах манифеста.
Итак, вот вопрос: как заставить регистрацию без COM работать с управляемым C# COM-сервером и собственной C ++ DLL в качестве COM-клиента?
Вот также файлы манифеста:
COM-сервер (C# DLL)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32"
name="OBSBluetoothHeartrate"
version="1.0.0.0"
processorArchitecture="amd64"/>
<clrClass clsid="{54667DC4-13CD-4D25-BB9E-C3BDDFAF019F}"
progid="OBSBluetoothHeartrate.HrmPlugin"
threadingModel="Both"
name="OBSBluetoothHeartrate.HrmPlugin"
runtimeVersion="v4.0.30319"/>
</assembly>
COM-клиент (C ++ DLL )
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32"
name="HrmPlugin"
version="1.0.0.0"
processorArchitecture="amd64"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32"
name="OBSBluetoothHeartrate"
version="1.0.0.0"
processorArchitecture="amd64"/>
</dependentAssembly>
</dependency>
</assembly>
Обновление от 17 января 2020
Я также добавил AssemblyIdentity в C ++ DLL на случай, если это поможет (как за вопрос в комментариях). Единственное, что изменилось, так это то, что теперь, когда он загружается параллельной системой, он получает идентификацию вместо (null) - идентификация не требуется, поскольку я не использую C ++ DLL в качестве COM-сервера. Однако я обновил манифест C ++ DLL и журнал sxstrace - теперь это технически «более правильно», поэтому, по крайней мере, мы знаем, что это не причина.
Обновление от 29 января 2020
Я случайно скопировал манифест DLL-сервера DLL C# как манифест C ++ DLL-клиента C ++. Теперь это обновлено до правильного. Удостоверьтесь, что дважды проверили это, но класс все еще не найден, даже если sxstrace говорит, что правильный dll найден и загружен. Я попробую создать контекст активации вручную, который был предоставлен как ответ, и доложу (и, конечно, пометьте его как правильный ответ, если я смогу заставить его работать с этим)