概述
主要就以C#中dll调用,C的数据类型移植,C的指针在C#中如何实现,还有很难受的指针函数(这个作者搞了好久),还有一个是结构体在C#中的实现,最后是结构体中联合体在C#中如何调用(这个也很难受)。因为作者是小白,所以这篇文章讲的不会很深入,就以这前天调用库函数遇到的问题跟大家分享一下,有好多地方也是不求甚解,但最终调用是成功了。
C#调用DLL
[DllImport("fun_ptr.dll", EntryPoint = "CallFromDll"]
public static extern void CallFromDll(IntPtr fun);
- 1
- 2
这个调用很easy,输入这两句代码,就可以吧dll中的函数callformdll拿出来用了。需要做的准备就是把封装好的dll放到c#的…binDebug目录下就可以了,可惜作者要调用的函数有点复杂,是涉及到指针传值的。
C指针在C#中的移植
在C中的指针,例如比较常用的char*指向一条字符串,在C中一般依靠指针去传递,那么在C#中如何获取呢?(不要问为什么要用这个举列子,恰好做到这个罢了),给个例子自己看:
这是在dll头文件中的函数声明:
#ifdef _WIN32
# ifdef DEVSDK2_EXPORTS
# define DEVSDK2_API __declspec(dllexport)
# else
# define DEVSDK2_API
# endif
#else
# define DEVSDK2_API __attribute__ ((visibility("default")))
#endif
DEVSDK2_API const char* checkLock();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
然后在C#中用IntPtr去提取,接着在转化成字符串,:
[DllImport("DevSDK2.dll", EntryPoint = "checkLock")]
public static extern IntPtr checkLock();
private void button1_Click(object sender, EventArgs e)
{
IntPtr str = checkLock();
string ss = Marshal.PtrToStringAnsi(str);
richTextBox1.Text = "***到期时间:"+ss;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
数据类型移植
OK,其实C/C++中还有许多数据类型的定义有着区别,作者整理了下,
这是C语言中常用的数据类型定义:
typedef unsigned char uint8_t; //无符号8位数 byte
typedef signed char int8_t; //有符号8位数 sbyte
typedef unsigned int uint16_t; //无符号16位数 UInt16
typedef signed int int16_t; //有符号16位数 short
typedef unsigned long uint32_t; //无符号32位数 UInt32
typedef unsigned long long uint64_t; //无符号64位数 UInt64
typedef signed long int32_t; //有符号32位数 int
typedef float float32; //单精度浮点数 float
typedef double float64; //双精度浮点数 double
typedef int bool;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
堆栈不对称解决办法
好吧尽管这么做了之后还有出现堆栈不对称的问题,比如:这是由于在调用时,两边的 数据不一致造成的。
解决方法有两种:
一:如果你可以修改dll源代码,那么恭喜你,你只需要做以下三步
1.在每个函数定义的时候定义成这个样子:
_LIBAPI void __stdcall CallFromDll(X x);
- 1
2.接着去C的导出目录,用文本的方式打开里面一个xxx.def文件,里面是dll函数的导出名字,会看到原本的:
EXPORTS
CallFromDll @1
- 1
- 2
变成了:
EXPORTS
CallFromDll@4 @1
- 1
- 2
3:.所以我们也灵活的将C#中的 [DllImport("fun_ptr.dll", EntryPoint = "CallFromDll"]
修改为 [DllImport("fun_ptr.dll", EntryPoint = "CallFromDll@4"]
就完成了
然而很遗憾,dll库文件是别人给的,还不写__stdcall,那我就只能修改C#的代码了,经过作者重重测试,发现在调用时下面增加字段,可以避免报错
[DllImport("fun_ptr.dll", EntryPoint = "CallFromDll",CallingConvention =CallingConvention.Cdecl), ]
public static extern void CallFromDll(IntPtr fun);
- 1
- 2
基本实现了C数据类型到C#中的移植过程。未完待续、、、
最后
以上就是无情舞蹈为你收集整理的C#调用C/C++动态链接库笔记(一)C#调用DLLC指针在C#中的移植数据类型移植堆栈不对称解决办法的全部内容,希望文章能够帮你解决C#调用C/C++动态链接库笔记(一)C#调用DLLC指针在C#中的移植数据类型移植堆栈不对称解决办法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复