这个.tlh文件是否正确,如果没有,那么我该如何生成正确的文件呢?

use*_*145 3 c# c++ com unmanaged managed

我试图从非托管C++代码调用.NET 4.0 DLL.

我按照Atul Mani的Code Project文章中的说明进行操作.

我构建了.NET dll,并遵循所有步骤,包括使用regasm注册它.

接下来,我创建了一个非托管C++项目,并在.cpp文件的开头添加了这一行:

#import "D:\PathToMyCSharpProject\bin\Debug\com.DeviceServices.tlb" rename ("EOF","adoEOF") no_namespace named_guids raw_interfaces_only
Run Code Online (Sandbox Code Playgroud)

当我构建C++项目时,在D:\ MyCPlusPlusProject\Debug中创建了一个.tlh文件.

接下来,我添加了CodeProject文章建议的代码,该文章尝试从C#库创建指向对象的指针.

CoInitialize(NULL);   //Initialize all COM Components

// <namespace>::<InterfaceName>
MyCSharpNamespace::IMyCSharpInterfacePtr pMyCSharpInterfacePtr;
Run Code Online (Sandbox Code Playgroud)

"MyCSharpNamespace"是我在C#项目中使用的命名空间.

当我构建C++项目时,我现在得到一个编译错误:

错误2错误C2653:'MyCSharpNamespace':不是类或命名空间名称

还有其他错误,因为它无法识别IMyCSharpInterfactPtr.

所以,我查看了.tlh文件,内容如下:

// Created by Microsoft (R) C/C++ Compiler Version 10.00.40219.01 (6478e0c7).
//
// MyCPlusPlusProjectPath\debug\com.deviceservices.tlh
//
// C++ source equivalent of Win32 type library MyCSharpProjectPath\bin\Debug\com.DeviceServices.tlb
// compiler-generated file created 05/27/14 at 11:52:16 - DO NOT EDIT!

#pragma once
#pragma pack(push, 8)

#include <comdef.h>

//
// Forward references and typedefs
//

struct __declspec(uuid("961b3c24-98f2-400e-8bea-ab357a18d851"))
/* LIBID */ __MyCSharpProject;

//
// Named GUID constants initializations
//

extern "C" const GUID __declspec(selectany) LIBID_MyCSharpProject =
    {0x961b3c24,0x98f2,0x400e,{0x8b,0xea,0xab,0x35,0x7a,0x18,0xd8,0x51}};

#pragma pack(pop)
Run Code Online (Sandbox Code Playgroud)

我在互联网上搜索了一下.tlh文件中的内容,并在msdn找到了#import页面.

它说.tlh文件的内容应该包括我的.tlh文件中不存在的智能指针声明(即IMyCSharpProjectInterfacePtr)和typeinfo声明.

MyCSharpProject声明了一个公共接口,包括一个生成的GUID,正确构建,并且我从文章中看到的所有步骤似乎都是成功的.

所以,我的问题是,有人可以建议为什么这些定义不存在于我的.tlh文件中应该存在吗?

Han*_*ant 7

.tlh文件不能出错,它是从COM服务器的类型库自动生成的.一个明显的缺陷是它很空,你根本看不到任何声明.

问题在于Codeproject.com的文章,这类项目的课程标准是缺少必要的步骤,没有解释实际发生的事情,并且经常使用非常糟糕的做法.为了使.NET类型可以从COM客户端使用,您必须明确将其设置为对COM客户端可见.将此属性添加到要导出的每个类型:

  [ComVisible(true)]
Run Code Online (Sandbox Code Playgroud)

将它应用于接口和类.

像作者提出的那样使用[Guid]属性是非常危险的.在开发库时可以将它保留在原位,它有助于避免注册表污染,并允许您跳过Regasm步骤(并非总是如此),但在运送库之前再次删除它非常重要.COM中一个坚如磐石的规则是对界面的修改需要一个新的guid,一个必不可少的DLL Hell对策.当您将其保留到CLR以自动生成一个时,您会自动获得一个新的.

在开发过程中最好避免在GAC中注册程序集,在GAC中留下过时的程序集副本会导致太多事故.使用/codebaseRegasm命令中的选项,这样就不需要了.您可以忽略您收到的警告.