0

首先祝大家新年快乐,希望你们一切都好!

我正在开发一个 C++ 项目,在该项目中我需要调用我在这篇文章的第一个答案之后创建的 C# DLL 。获得 DLL 后,我需要从 Qt 调用它,因此通过使用dumpcpp和 regasm 生成的.tlb文件,我设法让.cpp.h文件使用我的类。作为参考,类的命名空间是Wrapper,主类是Device和 guid {DD4A4896-C105-4C60-839B-B18C99C8FE15}

一旦我有生成的文件来使用DLL,如果我尝试在 Qt 上创建Wrapper:: Device实例,我会收到以下错误:

QAxBase::setControl: requested control {dd4a4896-c105-4c60-839b-b18c99c8fe15} could not be instantiated
QAxBase::qt_metacall: Object is not initialized, or initialization failed

它没有提供更多信息,所以我尝试检查 guid 是否存储在系统注册表中(我使用了之前引用的帖子中解释的 regasm 命令,它说它成功了,但你永远不知道)。打开注册表编辑器并搜索 Guid 显示它存在于:Computer\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{DD4A4896-C105-4C60-839B-B18C99C8FE15},据我所知,这是这些 guid 的正确路径,它指向正确的 DLL。

我虽然这可能是由于某种 ActiveQt 问题,并且正如之前引用的帖子解释了如何从 VS C++ 使用该 DLL,我决定试一试,将此用作另一个参考。我已经完成了这段代码,它应该创建我的设备对象的一个​​实例

#include <iostream>
#include <atlstr.h>
#import "C:\Users\javie\Documents\Wrapper\Wrapper\bin\x86\Release\netstandard2.0\Wrapper.tlb" named_guids raw_interfaces_only

inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); };

int main()
{

    try
    {
        TESTHR(CoInitialize(0));
        Wrapper::IDevicePtr devPtr = nullptr;
        TESTHR(devPtr.CreateInstance("{DD4A4896-C105-4c60-839B-B18C99C8FE15}"));
    }
    catch (const _com_error& e)
    {
        CStringW out;
        out.Format(L"Exception occurred. HR = %lx, error = %s", e.Error(), e.ErrorMessage());
        MessageBoxW(NULL, out, L"Error", MB_OK);
    }

    CoUninitialize();// Uninitialize COM

    std::cout << "Hello World!\n";
}

但是,这也不起作用, createInstance 方法会引发Class not registeredHR=80040154的异常。同样,根据注册表编辑器,该类已注册,所以我不明白错误。我也尝试过使用devPtr.CreateInstance("Wrapper.Device"),devPtr.CreateInstance("Wrapper::Device")或 `devPtr.CreateInstance("Wrapper::CLSID_Device") 作为我发布的链接的建议,但在这些情况下,我得到另一个例外,即 HR=800401f3和消息Invalid class string

VS 或 Qt Creator 是否以管理员身份打开并不重要,我得到完全相同的错误。我的想法已经用完了,我真的需要能够使用由 dumpcpp 生成的文件从 Qt 中使用该 DLL。

有谁知道会发生什么?我觉得很奇怪。

4

2 回答 2

0

如果您的 C++ 应用程序是 64 位的,那么答案就在那里,因为您的 C# 组件是 32 位的(或 MSIL,但已注册到 32 位配置单元)。在这种情况下,使用 VBScript 的简单测试总是有用的。

编写一个简单的 VB 脚本 (test.vbs)

Dim obj
Set obj = CreateObject("Wrapper.Device") ' or whatever your ProgID is
MsgBox TypeName(obj)

现在,以 2 种方式运行此宏:使用 32 位和 64 位版本的 VBScript:

32-bit > c:\windows\SysWow64\cscript.exe test.vbs
64-bit > c:\windows\system32\cscript.exe test.vbs

这是假设您的 C# 组件是调度兼容的。如果不是,那么它仍会为您提供可用于调试的不同结果。

假设自动化/IDispatch 兼容,如果您正确注册了组件,一个可以工作,一个不能工作。

你注册正确了吗?当我使用 regasm 时,我总是在为 COM 注册 C# 组件时使用开关 /tlb /codebase。

于 2020-12-31T15:52:56.280 回答
0

好的,如果有人发现同样的错误,我会解释我找到的解决方案。问题是,在我的例子中,我开发的 C# 类依赖于另一个 32 位 dll,它没有在我的 PC 上注册。一旦我注册了另一个 dll,一切正常。

我不知道为什么 VS 在我的类本身注册时一直告诉我该类未注册,它是未注册的依赖项之一。

无论如何,感谢约瑟夫的评论,我发现了这一点,非常感谢您的帮助。

于 2021-01-07T12:23:56.677 回答