C# 调用C++ CLR dll类库时,实现从 string 到 sbyte* 的转换
问题描述
今天在做项目的时候碰到一个问题,就是用C++编写CLR类库dll的时候,C++的函数参数列表中包含一个char*的输出型参数,然而在C#调用该dll时候,会自动将函数的中的char*参数“翻译”为sbyte*, 使用了各种方法都不能调用函数,主要是不能合适的转换为sbyte*。
简单示例
举个简单的例子,比如我有一个CLR的类库为MyDll.dll, 其中头文件为Mydll.h,简单的只有一个函数,其中我想要为char*的作为输出参数, 代码如下
// MyDll.h #pragma once
#include <cstdio>
#include <cstring>
using namespace System; namespace MyDll { public ref class MyClass
{
// TODO: 在此处添加此类的方法。
public:
MyClass()
{}
public:
static bool TestFunc(char* outPutStr, int *p)
{
*p = ;
char* s = "Hello world";
strcpy_s(outPutStr, , s);
return true;
}
};
}
源文件内容MyDll.cpp为空。【生成解决方案】后,得到MyDll.dll库。
// 这是主 DLL 文件, MyDll.cpp #include "stdafx.h" #include "MyDll.h"
然后新建一个C# WPF项目,右键 【引用】->【添加引用...】->左侧Tab【浏览】->右下角【浏览...】选择刚才生成的 MyDll.dll 文件后,点击【确定】。这样我们就可以在WPF项目中调用 TestFunc 函数了。
我们在 WPF 的 MainWidnow 中随便加入一个 Button,然后在 Button 的 Click 事件中尝试调用 TestFunc 函数,Mainwindow 的 cs 文件如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices; namespace MyWPF
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void Button_Click(object sender, RoutedEventArgs e)
{
unsafe
{
string str = new string('A', );
IntPtr intPtrStr = (IntPtr)Marshal.StringToHGlobalAnsi(str);
sbyte* sbyteStr = (sbyte*)intPtrStr; int p = ;
MyDll.MyClass.TestFunc(sbyteStr, &p); String tmp = new String(sbyteStr);
MessageBox.Show(tmp);
MessageBox.Show(p.ToString());
}
}
}
}
注意引入第 15 行的命名空间, 同时【项目】->【属性】->【生成】->勾选 【允许不安全代码】。 主要转换的部分出现在 33-35 行,首先建立一个普通的 string 变量,然后新建一个指针,指向该 string的内容,再讲该指针强制类型转化为sbyte*, 从而实现从 char* 中获取内容。
问题讨论
问题1: 为什么 C# 会将 C++ 中的 char* 转换为 sbyte* 呢?
这是因为 C++ 中的 char 占用一个字节,而 C#中 char 占用两个字节,所以不能讲 char* 直接转换为 C# 中的 char*, 而 sbyte 是有符号单字节,取值区间 [-128, 127],所以 C# 将 char* 转换成 sbyte* 是合理的。
问题2:CLR 的 dll 和普通的 dll (Native dll) 有什么区别呢?
CLR 有点类似于 java 的 “虚拟机” , 提供运行环境,负责检查 内存管理、安全、异常等比较容易出错的问题,提高程序的安全性和健壮性,是 .NET Framework 的主要引擎。在 CLR 监视下的代码称为 “托管代码 (managed)”, 而其他的不在其监管下的代码称为 “非托管代码 (unmanaged)”。在 CLR 环境下生成的代码是中间代码,有点类似于 java 的字节码。所以通过 CLR Dll 生成的 dll 类库是中间代码,普通的 dll 则是直接是本机化的二进制文件, 通过 CLR DLL 生成的 dll 是程序集 (Assembly), 可以在直接在C#工程中【添加引用】就可以直接调用,从前面的例子也可以看出来,不需要任何的 DllImport 之类的包含与结构体重定义,函数指针定义等等复杂的操作,使得调用更加简单。
源码下载
http://files.cnblogs.com/files/python27/MyWPF.zip
http://files.cnblogs.com/files/python27/MyDll.zip
C# 调用C++ CLR dll类库时,实现从 string 到 sbyte* 的转换的更多相关文章
- PB调用C#编写的Dll类库
在c# 中编写com组件,供PB调用实例 前言:c#中写的dll直接是不能被pb调用的,只有写成com组件才可以调用,所以用c#写dll时要注意. c#中新建类库 类库类型为通用类库,项目名为AddC ...
- 利用C#的反射机制动态调用DLL类库
最近由于业务要求,需要动态调用DLL类库,所以研究了一下,感觉还好也不太难,今天就把自己理解的写了一个小例子(已经通过VS2005跑通),供大家一起研究和探讨,有理解不当的地方还请高手们多多指正,谢谢 ...
- CLR调试时的sos.dll/clr.dll/mscorwks.dll/mscordacwks.dll等动态库的版本对应
大家都知道,在调试托管代码时,一定会加载到sos/clr/mscorwks/mscordacwks这些动态库,才能够很好的完成我们的调试工作,那么他们的版本对应关系是怎样的呢,特别是clr.dll/m ...
- .Net DLL类库引用时没有注释信息
自己编写的类库提供给别人引用时,别人获取不到DLL内部的方法.变量的注释信息,无法了解内部情况和使用方法. 原因:没有随DLL类库一同输出注释文档 解决方案: 在VS界面中选中提供给别人的类库项目 在 ...
- C#创建dll类库
类库让我们的代码可复用,我们只需要在类库中声明变量一次,就能在接下来的过程中无数次地使用,而无需在每次使用前都要声明它.这样一来,就节省了我们的内存空间.而想要在类库添加什么类,还需取决于类库要实现哪 ...
- 浅谈C++调用C#的DLL程序方法
把C#编译成DLL或者Axtive控件,再由C调用!比如使用C++调用C#的DLL. SwfDotNet是.net下输出flash的类库.SwfDotNet是C#编写的,作者的C#水平,真是令我佩服. ...
- 在C#调用C++的DLL方法(二)生成托管的DLL
写操作之前,还是扼要的说一下托管与非托管C++的区别好了,其实我也并没有深入了解过托管C++的特点所在,其最大的特征就是可以由系统来调试回收相关的代码资源,跟C#的特性一样,只是编程风格跟C++类似而 ...
- java调用C#的dll
链接地址:http://www.cnblogs.com/yinhaiming/articles/1712463.html .net产生的比java晚,其类库的封装在某些方面也比java更优秀,更全面. ...
- Python调用C# Com dll组件实战
之前公司有套C# AES加解密方案,但是方案加密用的是Rijndael类,而非AES的四种模式(ECB.CBC.CFB.OFB,这四种用的是RijndaelManaged类),Python下Crypt ...
随机推荐
- tensorflow生成随机数的操作 tf.random_normal & tf.random_uniform & tf.truncated_normal & tf.random_shuffle
tf.random_normal 从正态分布输出随机值. random_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name ...
- 参考 - spring boot 静态变量注入值
参考http://blog.csdn.net/zhayuyao/article/details/78553417 @Component public class A { private static ...
- SSH框架整合思想
--------------------siwuxie095 SSH 框架整合思想 1.SSH 框架,即 Struts2 ...
- js 放在公共头部 子页面引用js 失效问题
先回忆一下二者的区别(对于此篇文章而言,二者在用法上没有区别) jsp:include是先编译一下included.jsp文件,然后再包含 先编译,后包含 @ include是先把文件包含就来,然后统 ...
- mybatis框架的架构(图解)
1. mybatis配置 SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息. mapper.xml文件即sql映射文件,文件中配置了操作数 ...
- VC小笔记
1.strcpy不需要指定的长度,遇到被复制字符的串结束符’\0’才结束,容易溢出 2.memcpy(k, s, strlen(s)*sizeof(char)+1); // strlen(s) 后 + ...
- 关于bootstrap的认识
学习一个框架最好的方法当然就是去它的官网查看它的官方文档,看看官网是怎么描述这个框架的吧------Sleek, intuitive, and powerful front-end framework ...
- Scrum 项目3.0--软件工程
1. 确保product backlog井然有序.(参考示例图1) (例图1) 2.把故事进一步拆分成任务.(参考示例图2) (例图2) 3. 形成Sprint backlog. Scrum mast ...
- 练习并熟练掌握交互式 SQL 语言
哈工大数据库系统 实验:练习并熟练掌握交互式 SQL 语言 实验目的:基于给定的 OrderDB 数据库, 练习并熟练掌握交互式 SQL 语言实验环境:sql sever 2008 附:Order ...
- PhpStorm 注册相关
网址 http://idea.lanyus.com/ 最新(2017年9月)PhpStorm 2017.3 .WebStorm 2017.2.5.PyCharm 2016.3激活方式 打开网址 ht ...