首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何将字符串参数从C++传递给托管C# DLL

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

Stack Overflow用户
提问于 2016-09-30 14:09:24
回答 1查看 2.5K关注 0票数 2

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

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

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

EN

回答 1

Stack Overflow用户

发布于 2016-09-30 14:09:24

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

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

我就是这么做的。

C#码

下面是我的C#代码示例。有几件事要注意:

  • 您希望能够从C++调用的任何函数都必须在interface部分中被忽略。
  • 注意我在接口和函数定义中声明stringToPrint参数的方式。用string作为[MarshalAs(UnmanagedType.BStr)]的前缀是至关重要的。
  • 在函数中,您可以像使用普通字符串一样使用string参数。您不需要像在BSTR中使用C++那样从C#中转换。下面将更详细地介绍这一点。

.CS文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//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()函数。
  • 字符串必须作为C#类型变量传递给BSTR。将std::string转换为BSTR相当容易,我有两个方向的转换函数。

头文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//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);

    };
}

源文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//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());
    }
}

事情就是这样。如有任何问题,我会尽力回答。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39800759

复制
相关文章
C#访问非托管DLL
前段时间写了一个读卡器程序,使用到了一个DLL。在.NET 中调用DLL还是相当简单的。我也是转别人的代码,自己的不写。下面就是代码: C#中要使用动态链接库中的导出函数,只能在程序中根据DllAtribute显示调用,无法在运行阶段动态加载,但是我们可以利用WIN32 API的LoadLibrary和FreeLibrary打到目的,问题是根据GetProcAddress()函数获取到的导出函数的地址无法在C#中利用,网上很多方法多是利用对函数调用栈的操作来达到在C#中操作的目的.    其实如果导出函数
用户1105954
2018/01/12
1.5K0
如何将多个参数传递给 React 中的 onChange?
在 React 中,一些 HTML 元素,比如 input 和 textarea,具有 onChange 事件。onChange 事件是一个非常有用、非常常见的事件,用于捕获输入框中的文本变化。有时候,我们需要将多个参数同时传递给 onChange 事件处理函数,在本文中,我们将介绍如何实现这一目标。
网络技术联盟站
2023/06/07
2.7K0
C#调用C++ Dll
现在项目基本都是旁边C++的哥们做好dll扔给我,然后我调用。好久之前晚上down了一份c#调用c++dll的方法,出处早已经遗忘。闲来无事,放上来好了。原作者看到后可以留言,我会把您链接放上的,帮了我很多!!!
叁金
2018/09/04
3.5K0
LoadRunner参数传递给参数
需求:使用随机函数时,需要参数化某个参数,并且后面的步骤需要使用这个参数。 方法: 1 lr_save_string 该函数主要是将程序中的常量或变量保存为lr中的参数 2 lr_eval_string 从参数中取得对应的值,并且转换为一个字符串 测试: 在action里写: 1 lr_output_message("*****参数:%s********",lr_save_string(lr_eval_string("{NewParam}"),"name")); 2 lr_output_messag
全栈测试开发日记
2023/02/18
2.9K0
C#(.Net) 将非托管dll嵌入exe中
而大部分情况下,我们需要引用C++写的dll,如果你的dll是使用 DllImport来导入的,那么它就属于非托管dll,这种dll无法直接嵌入exe中,需要借助工具:Costura.Fody,该工具可以使用VS直接下载
DearXuan
2022/01/19
2.3K0
C#(.Net) 将非托管dll嵌入exe中
C#调用C++编写的DLL
1 把DLL放在C#工程的Debug文件夹跟Release文件夹,我这里是使用X86编译的就放在了这两文件夹
zls365
2020/08/19
2.2K0
C#调用C++编写的DLL
C#如何加载嵌入到资源的非托管dll
我们总会遇到需要加载非Win32的非托管dll,这里推荐一种方式就是将那些非win32的非托管dll嵌入资源的方式,在入口解压并且加载的方式,我先来看看如何实现吧,首先我们准备好demo,新增控制台项目如下:
ryzenWzd
2021/05/17
1.1K0
C#如何加载嵌入到资源的非托管dll
2019-3-7-手把手教你PInvoke
这个时候你就会接触到一些美妙的dll,比如user32.dll,kernal32.dll
黄腾霄
2020/06/10
9040
WinCE中解决“图片采集及压缩”问题的开发历程
   让WinCE工控板上的摄像头拍照,然后将图片数据通过GPRS发送到指定的主机数据库中。
用户1170933
2022/05/10
1.3K0
C#调用C++动态库接口函数和回调函数
需求: 当前C++已经写好了一个动态库,完成了产品开发需求,C#需要调用C++编写的动态库DLL接口,开发出完整的软件,DLL动态库里包含了普通接口函数,回调函数。
DS小龙哥
2022/05/23
2.8K0
C#调用C++动态库接口函数和回调函数
React篇(029)-如何将参数传递给事件处理程序或回调函数?
你可以使用箭头函数来包装事件处理器并传递参数: <button onClick={() => this.handleClick(id)} /> 这相当于调用 .bind: <button onClick={this.handleClick.bind(this, id)} />
齐丶先丶森
2022/05/12
3.8K0
在VS2010上使用C#调用非托管C++生成的DLL文件(图文讲解) 背景
背景      在项目过程中,有时候你需要调用非C#编写的DLL文件,尤其在使用一些第三方通讯组件的时候,通过C#来开发应用软件时,就需要利用DllImport特性进行方法调用。本篇文章将引导你快速
庞小明
2018/03/09
2.8K0
在VS2010上使用C#调用非托管C++生成的DLL文件(图文讲解) 背景
import duties(Python import变量)
最近在读《编程之美》,打算用C#实现其中一个题目,就是如何控制CPU的使用率在50%,使得在资源管理器中CPU利用率维持在一条直线。单核的还容易办到,但是现在的机器一般都是多核的,这样就需要调用Win32 API SetThreadAffinityMask 来给线程制定CPU去执行。但这个API只能在C++调用,那么在C#里如何调用呢?更进一步,就是在C#里为什么没有全部的WIN32 API可以调用呢?有没有方法可以实现呢?
全栈程序员站长
2022/07/31
1.1K0
C#调用C和C++函数的一点区别
最近做U800电话的二次开发,需要调用厂商的C函数库来打电话,后来想加入通话录音功能,但发现程序默认生产的WAV文件过大,又找了个WAV转MP3的C++函数库程序,出了点问题。下面是转MP3的程序接口(头文件): #ifndef _MP3ENC_H_ #define _MP3ENC_H_ int mp3_enc(const char* inWavName,int nRate,const char* outMP3Name); #endif 按照C#调用非托管程序的约定,声明一个对应的C#函数接口: [D
用户1177503
2018/02/26
1.7K0
c# 获取串口设备的输入(unsigned char *和 char*)
因为是C#,所以平台肯定是.NET了。 之前因为一个小小的业务需要接触了下密码键盘的操作。其实就是简单的获取用户输入密码的操作,没碰到什么大的问题,但是查资料的过程中还是感觉查到的东西挺多的,是那种越查越多,但是又不是很关键的东西。 在调用DLL中的方法的时候,我们一般要对照函数说明来把C/C++中的类型转换为.NET中相对应的类型,而且方法必须声明为静态外部函数,即加上public  extern static声明头.如果不加public ,函数默认为私有函数,调用就会出错。 [DllImport("CO
hbbliyong
2018/03/05
2.4K0
linux/bash:map作为参数传递给function
在linux bash中map是作为数组处理的,不能作为参数直接传递函数,如果一定要传递给函数,要做一些变通处理,示例如下:
10km
2019/08/14
2.7K0
升级到 dotnet core 之后 HandleProcessCorruptedStateExceptions 无法接住异常
这是 dotnet core 的破坏性改动之一,在 dotnet framework 里面,可以使用 HandleProcessCorruptedStateExceptionsAttribute 接住非托管层抛出的异常,如 C++ 异常等。但是这个功能在 dotnet core 下存在行为的变更,从 .NET Core 1.0 开始,损坏进程状态异常无法由托管代码进行处理。 公共语言运行时不会将损坏进程状态异常传递给托管代码
林德熙
2021/01/29
1K0
如何将代码托管到Github
Github是最火热的源代码管理平台,你可以通过这个平台,将代码托管起来,防止代码丢失,或者将自己的代码展示给世界。
宿春磊Charles
2022/03/29
7910
如何将代码托管到Github
C#中DllImport用法汇总
最近使用DllImport,从网上google后发现,大部分内容都是相同,又从MSDN中搜集下,现将内容汇总,与大家分享。
全栈程序员站长
2022/07/25
2.1K0
点击加载更多

相似问题

将参数从托管C#传递给托管C++

14

如何将结构从C#托管传递给C++非托管DLL并得到结构?

10

如何将C#委托函数传递给托管C++ .Dll?

10

将c#字符串传递给非托管c++ DLL

10

如何将变量参数va_list从托管C++传递给C#?

13
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文