繁体   English   中英

如何将字符串参数从 C++ 传递到托管 C# DLL

[英]How to pass a string argument from C++ to a managed C# DLL

我正在编写一个需要调用用 C# 编写的 DLL 的 C++ 程序。 我按照这些说明创建了我的 C# DLL 并从我的 C++ 链接到它。

https://support.microsoft.com/en-us/kb/828736

我有一个将字符串作为参数的 C# 函数。 如何将 C++ 中的字符串传递到 C# 中?

我找不到这个问题的简明答案,所以我把我的解决方案放在这里,希望它可以帮助将来的某个人。

TL;DR:您需要使用 BSTR 在 C# 和 C++ 之间来回传递字符串。

这是我如何做到的。

C# 代码

这是我的 C# 代码示例。 需要注意的几点:

  • 您希望能够从 C++ 调用的任何函数都必须在interface部分中声明。
  • 请注意我在接口和函数定义中声明stringToPrint参数的方式。 [MarshalAs(UnmanagedType.BStr)]开头的string至关重要。
  • 进入函数后,您可以像使用普通字符串一样使用string参数。 您不需要像在 C++ 中那样C# 中的BSTR进行转换。 更多关于下面的内容。

.CS 文件

//Reference where I got all this:
//https://support.microsoft.com/en-us/kb/828736

// Class1.cs
// A simple managed DLL that contains a method to add two numbers.
using System;
using System.Runtime.InteropServices;


namespace ManagedDLL
{
    // Interface declaration.
    public interface ICalculator
    {
        //Test functions
        int Add(int Number1, int Number2);
        int ReturnAge();
        string StringTest();
        void PrintAString([MarshalAs(UnmanagedType.BStr)] string stringToPrint);
    };

    // Interface implementation.
    public class ManagedClass : ICalculator
    {
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //Test functions
        public int Add(int Number1, int Number2)
        {
            return Number1 + Number2;
        }

        public int ReturnAge()
        {
            return 35;
        }

        public string StringTest()
        {
            return "Can you hear me now?";
        }

        public void PrintAString([MarshalAs(UnmanagedType.BStr)] string stringToPrint)
        {
            Console.WriteLine("Trying to print a BSTR in C#");

            Console.WriteLine(stringToPrint);
            Console.WriteLine("Done printing");
        }
    }
}

C++代码

在 C++ 中需要注意的一些事情:

  • 标头中的#import调用。 这是您告诉 C++ 如何找到您的 C# 库的地方。 我在问题中链接到的教程中提到了这一点。
  • 如果您的 C# 函数之一中有返回值,则它不会作为返回值传递给 C++。 相反,您需要在调用时包含一个指向 C++ 变量的指针作为参数。 有关此示例,请参阅AddTest()函数。
  • 字符串必须作为BSTR类型变量传递给 C#。 std::string转换为BSTR相当容易,我有在任一方向进行转换的函数。

头文件

//csLink.h

#include <windows.h>
#include <iostream>
#include <string>

#import "path/to/C#/dll.tlb" raw_interfaces_only

using namespace std;

namespace Sample{

    class CSLink {
    public:
        CSLink();
        //Test functions
        int AddTest(int i1, int i2);
        int AgeTest();
        string StringTestCall();
        void stringArgTest(string s);

    private:
        ICalculatorPtr pCalc;
        long lResult;

        string convertBSTR(BSTR *s);
        BSTR convertBSTR(string s);

    };
}

源文件

//csLink.cpp

#include "stdafx.h"
#include "csLink.h"

using namespace std;

namespace Sample{
    //Constructor
    CSLink::CSLink(){
        cout << "You have created a CS Link" << endl;

        //https://support.microsoft.com/en-us/kb/828736
        HRESULT hr = CoInitialize(NULL);

        pCalc = ICalculatorPtr(__uuidof(ManagedClass));

        lResult = 0;
    }

    //Test functions
    int CSLink::AddTest(int i1, int i2){
        cout << "you are adding " << i1 << " and " << i2 << endl;

        pCalc->Add(i1, i2, &lResult);

        cout << "The result should have been " << i1 + i2 << " and it was " << lResult << endl;

        return 0;
    }

    int CSLink::AgeTest(){
        cout << "Trying to get my age" << endl;

        pCalc->ReturnAge(&lResult);

        return lResult;
    }

    string CSLink::StringTestCall(){
        BSTR s;
        pCalc->StringTest(&s);

        return convertBSTR(&s);
    }

    void CSLink::stringArgTest(string s)
    {
        //References I used figuring this all out:
        //http://stackoverflow.com/questions/28061637/how-to-pass-string-parameters-between-c-and-c
        //https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute(v=vs.110).aspx
        //http://forums.codeguru.com/showthread.php?193852-How-to-convert-string-to-wstring
        //http://stackoverflow.com/questions/6284524/bstr-to-stdstring-stdwstring-and-vice-versa

        BSTR bSTR = convertBSTR(s);

        cout << "~~~~~~~~~~~~~~~~~~~~~~~" << endl;
        cout << "Testing conversion: " << convertBSTR(&bSTR) << "|end test" << endl;
        pCalc->PrintAString(bSTR);
        cout << "~~~~~~~~~~~~~~~~~~~~~~~" << endl;
    }

    //Utility functions
    string CSLink::convertBSTR(BSTR *s){
        if (*s == nullptr){
            return "NULL STRING";
        }
        else{
            wstring ws(*s, SysStringLen(*s));
            string ss(ws.begin(), ws.end());
            return ss;
        }
    }

    BSTR CSLink::convertBSTR(string s){
        wstring wStr = wstring(s.length(), L' ');
        copy(s.begin(), s.end(), wStr.begin());

        return SysAllocStringLen(wStr.data(), wStr.size());
    }
}

就是这样。 有任何问题可以评论,我会尽力回答。

暂无
暂无

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

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