【问题标题】:Calling C# from C++, difficulties with "." in C# namespace从 C++ 调用 C#,使用“.”有困难在 C# 命名空间中
【发布时间】:2011-10-27 15:59:01
【问题描述】:

首先,我承认我对这个有点吹毛求疵——我漂亮干净的示例代码在我将它嵌入现实世界时不起作用。话说……

我有一个名为 CPierce.CSharpCall.dll 的 DLL,其中包含类似以下 C# 的内容:

namespace CPierce.CSharpBridge
{
    [System.Runtime.InteropServices.Guid("3D08DF02-EFBA-4A65-AD84-B08ADEADBEEF")]
    public interface ICSide
    {
        // interface definition omitted...
    }
    [System.Runtime.InteropServices.Guid("CBC04D81-398B-4B03-A3D1-C6D5DEADBEEF")]
    public partial class CSide : ICSide
    {
        // class definition omitted...
    }
}

这是用regasm /tlb等注册的。然后,我的C++代码看起来像这样:

#import "CPierce.CSharpCall.tlb" named_guids

    // Contains syntax errors!
int myfunc()
{
    HRESULT hRes = S_OK;
    CoInitialize(NULL);
    CPierce.CSharpBridge::ICSide *pManagedInterface = NULL;

    hRes = CoCreateInstance(
            CPierce.CSharpBridge::CLSID_Class1, 
            NULL, CLSCTX_INPROC_SERVER, 
            CPierce.CSharpBridge::ICSide, 
            reinterpret_cast<void**> (&pManagedInterface));

    // Calls to the interface omitted....

    CoUninitialize();
    return 0;
}

当然,问题在于 CPierce.CSharpBridge 的语法错误。我知道在 C++ 中,如果我想拥有与 C# 代码类似的命名空间,我可以说:

namespace CPierce
{
    namespace CSharpBridge
    {
        // definitions go here
    }
}

但我认为这不是我要在这里寻找的,因为我只需要引用另一个命名空间中的两个常量,而无需将整个方法放在该命名空间中。

什么是我需要完成对CoCreateInstance 的调用的C++ 语法?


更新:在更深入(更深入)的检查中,我发现我由 regasm 创建的 .tlb 文件几乎是空的。当我将所有源代码连接到一个 .cs 文件并编译时:

csc /debug /t:library BigFile.cs 
regasm BigFile.dll /tlb:BigFile.tlb

我得到了一个很大(而且很有用)的 tlb 文件。

当我从 Visual Studio 编译整个项目时,我得到了一个 .DLL 文件,但 regasm 并没有对它做任何事情,而是生成了一个最小的 .tlb 文件。 (ildasm 显示两个 DLL 之间几乎没有区别)

如果我在 Visual Studio 中编译 BigFile.cs,我会得到一个同样无用的 DLL。

我被难住了。

【问题讨论】:

  • 你试过用::代替.吗?
  • 是的。不过有些奇怪...如果我在对象浏览器中单击 .tlb,则会将其列为 CPierce_CSharpBridge。现在,CPierce_CSharpBridge::ICSide 返回为“ICSide 不是 PR1_CSharpBridge 的成员”。没有解决,但无论如何都不同。
  • 如果您没有有嵌套的命名空间,它会起作用吗?
  • 我的问题可能更深一些,.tlb 文件中几乎没有任何内容——我不确定我的类型/接口是否已完全注册。 regasm 没有给出错误,但我没有从中得到有用的 .tlb 。我有一个默认构造函数……是时候仔细看看 regasm 了。
  • 对我来说“。”在使用 regasm 生成 tlb 时被“_”替换。只需使用 Visual Studio 打开 tlb 文件即可显示问题。

标签: c# c++ com


【解决方案1】:

C++ 不使用. 运算符来分隔命名空间;它使用::。您将使用CPierce::CSharpBridge 而不是CPierce.CSharpBridge。不幸的是,这似乎对您没有帮助,因为您不知道 TLB 实际生成的命名空间是什么。

一个简单的解决方案是根本不使用命名空间并在没有它们的情况下导入:

#import "CPierce.CSharpCall.tlb" named_guids no_namespace

【讨论】:

  • 实际上,将其更改为使用 CPierce.CSharpBridge::ICSide 会给我错误 CPierce is not a class or namespace name。抱歉,我也试过了。
  • @clintp: CPierce::CSharpBridge::ICSide.
  • 是的,对不起,这就是我的意思。所有冒号,仍然是一个错误。
  • @clintp:你可以忽略命名空间吗?
  • @clintp - 更新您的问题并发布您当前使用的内容以及您收到的确切编译错误。我假设 dll 位于某个位置,并且您以正确的方式链接到它,您似乎不需要那么多帮助。
【解决方案2】:

这似乎是 C#/Visual Studio 方面的问题。我将放弃这个问题并打开一个适当的问题。感谢您帮助缩小范围。

【讨论】:

    猜你喜欢
    • 2013-09-27
    • 1970-01-01
    • 2011-05-05
    • 2014-07-17
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    相关资源
    最近更新 更多