将C语言编译成DLL并用C#进行调用以及关于从C#传输中文路径到C的DLL中打开文件的问题
2016-03-01 14:36
781 查看
动态链接库(Dynamic
Link Library 或者 Dynamic-link Library,缩写为 DLL),是window系统的基石。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个
DLL 文件中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。从语言方面来说就是可以在一定程度上使不同的语言之间实现相互调用。本文将实现一个将C语言编译成DLL,供C#调用的例子!
使用环境:vs2012专业版(11.0.50727.1 RTMREL)+ win8.1企业版
1、新建DLL工程
新建项目->win32->win32项目->应用程序设置->Dll
2、新建testDll.h和testDll.cpp文件,源文件后缀名必须为.cpp
testDll.h文件内容
testDll.cpp文件内容
3、生成项目的解决方案,在项目的debug目录下可以找到生成的TestDllWin32.dll文件
4、新建C#控制台应用程序
在Program.cs中引入System.Runtime.InteropServices,使用DllImport函数引入Dll文件,再使用extern关键字引入所要使用的函数
注意:必须将生成的TestDllWin32.dll文件放到程序的bin目录下的debug目录中,否则必须使用绝对路径引用Dll文件
Program.cs文件内容
5、测试结果
------------------------2016.3.12更新-------关于从C#传输中文路径到C里面打开文件的问题-----------------------------
问题:如果从C#传递到C编译而成的DLL中的字符串是一个需要打开的文件的路径名,并且路径名包含中文字符串,那么以上的传递方法将会出现问题,文件无法打开,个人粗浅理解:由于编码格式出错,原因如下图:
注:C语言编译而成的DLL中的CparseXmlFileName方法,只输出传入进去的字符串
传入的字符串:C:\\Users\\TwinklingZ\\Desktop\\ProjectOfTeacher\\minixml解析应用\\Label1.prt
即使使用UTF8的编码(Encoding.UTF8.GetBytes(Filename))也会出错:
解决办法,使用IntPtr类型,代码如下:
class Program
{
const string miniXmlDll = "miniXmlDll.dll";
[DllImport(miniXmlDll, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static IntPtr CparseXmlFileName(IntPtr str);
static void Main(string[] args)
{
string Filename = "C:\\Users\\TwinklingZ\\Desktop\\ProjectOfTeacher\\minixml解析应用\\Label1.prt";
var ptr = Marshal.StringToHGlobalAnsi(Filename);
/*
* 测试文件
*/
IntPtr re = CparseXmlFileName(ptr);
Marshal.FreeHGlobal(ptr);
string refile = Marshal.PtrToStringAnsi(re);
Console.WriteLine("FileName:" + refile);
Console.ReadKey();
}
}测试结果:
OK,搞定
Link Library 或者 Dynamic-link Library,缩写为 DLL),是window系统的基石。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个
DLL 文件中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。从语言方面来说就是可以在一定程度上使不同的语言之间实现相互调用。本文将实现一个将C语言编译成DLL,供C#调用的例子!
使用环境:vs2012专业版(11.0.50727.1 RTMREL)+ win8.1企业版
1、新建DLL工程
新建项目->win32->win32项目->应用程序设置->Dll
2、新建testDll.h和testDll.cpp文件,源文件后缀名必须为.cpp
testDll.h文件内容
<span style="font-size:18px;"> #ifndef Test_Dll #define Test_Dll extern "C" _declspec(dllexport) char* testChar(char* str);//测试字符串当参数带入以及返回 extern "C" _declspec(dllexport) int testInt(int a,int b);//测试整形,其余浮点型,双精度类似 #endif</span>
testDll.cpp文件内容
<span style="font-size:18px;"> #include "stdafx.h" #include "testDll.h" //以上两个头文件不能调换位置,stdafx.h头文件必须放在第一个,否则将会出错 char* testChar(char* str)//测试字符串当参数带入以及返回 { return str; } int testInt(int a,int b)//测试整形,其余浮点型,双精度类似 { return a + b; }</span>
3、生成项目的解决方案,在项目的debug目录下可以找到生成的TestDllWin32.dll文件
4、新建C#控制台应用程序
在Program.cs中引入System.Runtime.InteropServices,使用DllImport函数引入Dll文件,再使用extern关键字引入所要使用的函数
注意:必须将生成的TestDllWin32.dll文件放到程序的bin目录下的debug目录中,否则必须使用绝对路径引用Dll文件
Program.cs文件内容
<span style="font-size:18px;">namespace Test { class Program { [DllImport("TestDllWin32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] extern static IntPtr testChar(byte[] str); [DllImport("TestDllWin32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] extern static int testInt(int a, int b); static void Main(string[] args) { //使用字符串作为参数传入和接收返回的字符串 string str = "hello world"; IntPtr ch = testChar(Encoding.ASCII.GetBytes(str)); string result = Marshal.PtrToStringAnsi(ch); Console.WriteLine("testChar:\n" + result);//输出:testChar:hello world //int,float,double类型的传递 int a = 3; int b = 4; int reint = testInt(a, b); Console.WriteLine("testInt:\n" + reint);//输出:testInt:7 Console.ReadKey(); } } }</span>
5、测试结果
------------------------2016.3.12更新-------关于从C#传输中文路径到C里面打开文件的问题-----------------------------
问题:如果从C#传递到C编译而成的DLL中的字符串是一个需要打开的文件的路径名,并且路径名包含中文字符串,那么以上的传递方法将会出现问题,文件无法打开,个人粗浅理解:由于编码格式出错,原因如下图:
注:C语言编译而成的DLL中的CparseXmlFileName方法,只输出传入进去的字符串
传入的字符串:C:\\Users\\TwinklingZ\\Desktop\\ProjectOfTeacher\\minixml解析应用\\Label1.prt
即使使用UTF8的编码(Encoding.UTF8.GetBytes(Filename))也会出错:
解决办法,使用IntPtr类型,代码如下:
class Program
{
const string miniXmlDll = "miniXmlDll.dll";
[DllImport(miniXmlDll, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static IntPtr CparseXmlFileName(IntPtr str);
static void Main(string[] args)
{
string Filename = "C:\\Users\\TwinklingZ\\Desktop\\ProjectOfTeacher\\minixml解析应用\\Label1.prt";
var ptr = Marshal.StringToHGlobalAnsi(Filename);
/*
* 测试文件
*/
IntPtr re = CparseXmlFileName(ptr);
Marshal.FreeHGlobal(ptr);
string refile = Marshal.PtrToStringAnsi(re);
Console.WriteLine("FileName:" + refile);
Console.ReadKey();
}
}测试结果:
OK,搞定
相关文章推荐
- c#调用COM组件
- FREEBASIC 编译可被python调用的dll函数示例
- Linux C函数参考手册(PDF版)
- C#实现把指定数据写入串口
- C#动态创建button的方法
- C#中抽象方法与虚拟方法的区别
- c#中虚函数的相关使用方法
- C#实现给图片加水印的方法
- C#使用加边法计算行列式的值
- C#实现多线程的同步方法实例分析
- C#中尾递归的使用、优化及编译器优化
- DLL(Dynamic Linkable Library) 详解说明
- C#中的delegate委托类型基本学习教程
- C#实现子窗体与父窗体通信方法实例总结
- C#通用邮件发送类分享
- 举例讲解C#中自动实现的属性
- C#中this的用法集锦
- C#数据结构之顺序表(SeqList)实例详解