从 C++ 调用 C#,返回值

call c# from c++, return value

本文关键字:返回值 调用 C++      更新时间:2023-10-16

我正在尝试从C++调用C#代码。所以我选择了 COM 互操作方式。现在我有 C# 代码:

namespace ToBeCalled
{
    [Guid("9329feaf-b293-4093-a7d8-6128f52b30a6")]
    [ComVisible(true)]
    public interface IInterface
    {
        int Write(string toWrite);
    }
}
namespace ToBeCalled
{
    [Guid("e4105e40-2d6b-4b7c-ae42-d2f9c405a2a0")]
    [ComVisible(true)]
    public class ClassYouWantToUse : IInterface
    {
        public int Write(string toWrite)
        {
            System.Console.WriteLine(toWrite);
            return 1;
        }
    }
}

和 C++ 代码

#import "...\ToBeCalled.tlb"
int _tmain(int argc, _TCHAR* argv[])
{
    // Initialize COM.
    HRESULT hr = CoInitialize(NULL);
    // Create the interface pointer.
    ToBeCalled::IInterfacePtr piTest(__uuidof(ToBeCalled::ClassYouWantToUse));
    long lResult = 0;
    // Call the Add method.
    piTest->Write("hi", &lResult);
    wprintf(L"The result is %dn", lResult);
    // Uninitialize COM.
    CoUninitialize();
    return 0;
}

当我尝试这个编译时,它当然说 Write 不需要 2 个参数。我看到了MSDN,他们有这样的例子,他们以这种方式获取返回值。所以我的问题是,如何获取函数的返回值?当我将呼叫更新到

piTest->Write("hi");

比在未处理的异常上执行失败。当我在没有返回值的情况下尝试此示例时,因此方法的返回值声明无效,一切正常。

您的服务器代码正常,不需要使用 out 参数。

客户端代码应如下所示:

long result = piTest->Write("hi");

如果您查看生成的.tlh文件内部,您将看到签名类似于:

long Write(_bstr_t toWrite);

这是一个生成的包装器代码,您可能会将其与原始 COM 调用混淆,后者也是 tlh 文件的一部分,如下所示:

virtual HRESULT __stdcall raw_Write(BSTR toWrite, long* pRetVal) = 0;

包装器更方便:它在内部调用原始 COM 调用并处理返回值 - 因此,返回值通常从函数返回(而不是作为[out, retval]参数),如果原始调用的结果表示错误(失败的HRESULT),则会抛出_com_error异常。

有关详细信息,您可以查看另一个扩展名为tli生成的文件,其中包含包装方法的实现。