我正在尝试从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");


比未处理异常执行失败。当我尝试不带返回值的示例时,方法的返回值声明为void,那么一切正常。

最佳答案

您的服务器代码正常,您无需使用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的生成文件,该文件包含wrapper方法的实现。

关于c# - 从c++调用C#,返回值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36788929/

10-17 02:25