【问题标题】:call c# from c++, return value从 c++ 调用 c#,返回值
【发布时间】:2016-08-15 19:05:46
【问题描述】:

我正在尝试从 C++ 调用 C# 代码。所以我选择了COM Interop方式。现在我有了 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 %d\n", lResult);

    // Uninitialize COM.
    CoUninitialize();
    return 0;
}

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

piTest->Write("hi");

在未处理的异常上执行失败。当我尝试这个没有返回值的例子时,方法的返回值声明是无效的,然后一切正常。

【问题讨论】:

  • 我发现需要在c#中添加参数,然后我可以使用第二个参数来获得结果值。好的,所以对于 Int 问题解决了,但是我怎样才能发送这样的字符串呢?
  • 您应该能够正常返回一个值,而不是通过[out] 参数。究竟是什么异常?您是否调试过托管调用?

标签: c# c++ com unmanaged managed


【解决方案1】:

您的服务器代码没有问题,您不需要使用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] 参数),如果原始的结果call 表示错误(失败的HRESULT)抛出_com_error 异常。

具体可以看另一个生成的文件,扩展名为tli,里面包含了wrapper方法的实现。

【讨论】:

  • 谢谢,我试试。是的,我对 HRESULT 感到困惑。当我从 c# 返回字符串时,是否需要在这里进行一些释放?如果是,怎么做?
  • 你没有返回一个字符串,所以没有什么可以释放的。如果您创建一个返回字符串的新方法(在idl 定义中定义为[out, retval] 参数),它符合标准COM 规则,通常您必须通过SysFreeString API 释放它(例如,如果您使用原始调用)。但是,#import 也会生成一个“智能”包装器,该包装器将返回一个 bstr_t,它会为您解除分配,因此如果您使用该方法,则无需解除分配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多