简体   繁体   English

这个COM接口可以用C#实现吗?

[英]Can this COM interface be implemented in C#?

A COM component is currently implemented in C++ and the next version must be implemented in C#. COM 组件目前是用 C++ 实现的,下一个版本必须用 C# 实现。 The component is called from C++ (not CLI) code.该组件是从 C++(不是 CLI)代码调用的。 The major part of the not so small component is already ported to C#, but I have trouble to figure out how one specific method can be translated.不是那么小的组件的主要部分已经移植到 C#,但我很难弄清楚如何翻译一种特定的方法。

Interface definition接口定义

The following imports are used in the IDL: IDL 中使用了以下导入:

import "oaidl.idl";
import "ocidl.idl";

The major part of the interface is already translated to the corresponding C# attributes, interfaces and classes.接口的主要部分已经转换为相应的 C# 属性、接口和类。 Most of it works without problems.它的大部分工作没有问题。

But one of the interface members is defined in IDL as但是接口成员之一在 IDL 中定义为

    [
        object,
        uuid(<guid>),
        helpstring("Help"),
        pointer_default(unique)
    ]
    interface IStuff : IUnknown
    {
...
        HRESULT GetShortText([in] int i, [in] BOOL b, [out, string] TCHAR shortText[10]);
...
    }

Usage用法

To use the interface, a local TCHAR[10] array is passed as the name of the array (therefore, as a TCHAR* ).要使用该接口,将本地TCHAR[10]数组作为数组的名称(因此,作为TCHAR* )传递。 The COM server must put a short string in the TCHAR array. COM 服务器必须在 TCHAR 数组中放置一个短字符串。

Problem问题

I can't manage to call the method.我无法调用该方法。 Breakpoints set in the C# COM server in the GetShortText method are never hit.在 C# COM 服务器中GetShortText方法中设置的断点永远不会被命中。 COM simply doensn't find my implementation in .NET. COM 根本没有在 .NET 中找到我的实现。

How can this method that is called with a fixed size TCHAR* be correctly implemented in C#?这个以固定大小TCHAR*调用的方法如何在 C# 中正确实现?

I am not aware of any standard marshalling for this rather unusual construct.我不知道这个相当不寻常的构造有任何标准编组。 You might do the following, however:但是,您可以执行以下操作:

void GetShortText(int i, [MarshalAs:UnmanagedType.Bool] bool b, IntPtr shortTextPtr)
{
    string s = "Test";
    byte[] buffer;
    if (UseUnicode)
        buffer = Encoding.Unicode.GetBytes(s + '\0');
    else
        buffer = Encoding.Default.GetBytes(s + '\0');
    Marshal.Copy(buffer, 0, shortTextPtr, buffer.Length);
}

Notes:笔记:

  • a range check on buffer.Length (<= 10 for ANSI, <= 20 for UNICODE) should be added应该添加对 buffer.Length 的范围检查(对于 ANSI,<= 10,对于 UNICODE,<= 20)
  • The + '\\0' is for null-terminating the returned string + '\\0'用于空终止返回的字符串

This sort of interface can be implemented in .Net by specifying the parameter as an IntPtr and manually marshalling the string.通过将参数指定为IntPtr并手动编组字符串,可以在 .Net 中实现这种接口。 A full demo can be found on Github .可以在 Github找到完整的演示。

Example Implementation:示例实现:

[ComVisible(true), Guid("E559D616-4C46-4434-9DF7-E9D7C91F3BA5"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStuff
{
    void GetShortTest(int i, [MarshalAs(UnmanagedType.Bool)] bool b, IntPtr shortText);
}

[ComVisible(true), ProgId("InProcTargetTest.Class1"), Guid("BA5088D4-7F6A-4C76-983C-EC7F1BA51CAA"), ClassInterface(ClassInterfaceType.None)]
public class Class1 : IStuff
{
    public void GetShortTest(int i, bool b, IntPtr shortText)
    {
        var data = Encoding.Unicode.GetBytes("Hello");
        Marshal.Copy(data, 0, shortText, data.Length);
    }
}

Example caller:示例调用者:

if (FAILED(CoInitialize(nullptr))) {
    std::cout << "Failed to initialize COM\n";
}

IStuff *pStuff = nullptr;
CLSID clsClass1 = { 0 };
if (FAILED(CLSIDFromProgID(L"InProcTargetTest.Class1", &clsClass1))
    || FAILED(CoCreateInstance(clsClass1, nullptr, CLSCTX_INPROC_SERVER, IID_IStuff, (LPVOID*)&pStuff))) {
    std::cout << "Failed to create COM instance\n";
}

TCHAR test[10] = { 0 };
pStuff->GetShortTest(5, true, test);

std::cout << "From C#: " << test << "\n";

Example IDL:示例 IDL:

import "unknwn.idl";

[
    odl,
    uuid(E559D616-4C46-4434-9DF7-E9D7C91F3BA5),
    version(1.0),
    pointer_default(unique),
    custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "InProcTargetTest.IStuff")

]
interface IStuff : IUnknown {
    HRESULT _stdcall GetShortTest(
        [in] long i,
        [in] BOOL b,
        [out, string] TCHAR shortText[10]);
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM