VC2015编写的DLL给其他语言调用

本文详细介绍如何在C++Builder6、Delphi7、VB6及C#中调用DLL文件,包括设置调用约定、函数声明等步骤,并提供具体示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)用C++builder6调用DLL

用VC2015创建包含MFC库的DLL,如果是给C++Builder6使用,步骤如下:
1、工程属性==》C++==》高级==》调用约定  选项为:__stdcall (/Gd)

2、VC++2015中的函数声明如下:
   extern "C" __declspec(dllexport)  VOID __stdcall CreateMeter(const char* szTypeName);

3.VC++2015的def文件,EXPORTS可以不用写,因为C++Builder6不用到这个.lib文件
  不过,我发现要导出函数,需要在def字声明,否则在其他语言中找不到函数,提示错误.

4.在C++Builder6中,需要重新导出DLL的引导库.lib,方法如下:
  implib my.lib my.dll

  在BCB6工程中引入my.lib,同时添加函数声明,也就是VC2015DLL中的函数声明(与第2步相同)


(2)用Delphi7调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
unit ScaleWeight_dll;
interface
       procedure  CreateMeter(xktype:PChar;
       No:integer;
       Comm:integer;
       baud:integer;
       parity:Char;
       databit:integer;
       stopbit:integer
       );stdcall;external 'YuComm.dll';
       //获取重量字符串
       function  GetWeight( buff :pchar;index :integer 1):PChar;stdcall;
       external 'YuComm.dll';
       //写串口
       procedure WritePort( buff :array of byte;index :integer 0);stdcall;
       external 'YuComm.dll';
       function ClosePort(index :integer=1):integer;stdcall;external 'YuComm.dll';
       //name 'ClosePort1';
 
       //辅助函数
       //缓取缓冲区数据量
       function GetBuffLength(index :integer =0):integer;stdcall;
       external 'YuComm.dll';
       //或取通信状态;true串口打开但通信中断,false通信正常
       function GetStatus(index :integer =0):boolean;stdcall;external 'YuComm.dll';
       //清除缓冲区数据
       //procedure Clear(index :integer =0);stdcall;external 'YuComm.dll';
       //获取原始数据
       function  GetSourceData( buff :pbyte;index :integer 0):integer;stdcall;
       external 'YuComm.dll';
        
implementation
 
end.

将上面文件保存为扩展名为pas的文件,添加到delphi7工程中.

(3)在VB6中调用DLL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Private Declare Function CreateMeter Lib "YuComm"(ByVal name As String, _
ByVal No As Integer, _
ByVal port As Integer, _
ByVal baud As Integer, _
ByVal parity As Integer, _
ByVal databit As Integer, _
ByVal stopbit As IntegerAs Boolean'需要添加一个返回值声明,即使不需要
Private Declare Function GetWeight Lib "YuComm"(ByVal buff As String
Optional ByVal index As Integer = 1) As Long
Private Declare Function GetStatus Lib "YuComm"(Optional ByVal index As Integer = 1) 
As Integer
Private Declare Function ClosePort Lib "YuComm"(Optional ByVal index As Integer = 1) 
As Boolean
 
  
Private Sub Command1_Click()
  Dim name As String
  Dim port As Integer
  Dim baud As Integer
   
  name = Combo1.Text
  port = CInt(Text1.Text)
  baud = CInt(Text2.Text)
  CreateMeter name, 1, port, baud, 110, 8, 1
   
End Sub
 
Private Sub Command2_Click()
  ClosePort (1)
End Sub
 
Private Sub Command3_Click()
 
End Sub
 
Private Sub Timer1_Timer()
   Dim re As Boolean
    
   re = GetStatus(1)
   If re = True Then
     Label2.Caption = "串口打开成功"
   Else
     Label2.Caption = "串口打不成功"
   End If
    
   Dim buff1  As String
   buff1 = Space(100)
   Call GetWeight(buff1, 1)
   Label1.Caption = buff1
    
End Sub

在XP平台下,用VB6调用,请用release方式编译,否则VB6会提示找不到相应的DLL文件,即所这个文件就在运行目录下

在VB中调用,声明函数时应加上返回值,即使DLL中这个函数没有返回值.返回值的类型可任意

(4)在C#中调用DLL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
public partial class Form1 : Form
    {
        //========================================================================
        //1、创建仪表,并打开仪
        [DllImport("YuComm.dll")]
        public static extern bool CreateMeter(string xktype,int no,int comm,
        int baud,int parity,int databit,int stopbit);
        //2、读取仪表重量,多台仪表时,参数为索引
        [DllImport("YuComm.dll")]
        public static extern string GetWeight(StringBuilder weight, int index = 1);
        //写串口
        [DllImport("YuComm.dll")]
        public static extern void Write(ref byte buff,int index = 1);
        //3、关闭串口
        [DllImport("YuComm.dll")]
        public static extern void ClosePort( int index=1);
     
 
 
        //ScaleWeight辅助功能函数:获取缓冲区数据个数
        [DllImport("YuComm.dll")]
        public static extern int GetBuffLength(int index = 1);
        //获取通信状态:false通信正常 ,true通信中断
        [DllImport("YuComm.dll")]
        public static extern bool GetStatus(int index=1);
        //辅助功能函数:读取原始数据流
        [DllImport("YuComm.dll")]
        public static extern int GetSourceData(ref byte buff, int index = 1);
        //辅助功能函数:清除缓冲区
        //[DllImport("YuComm.dll")]
        //public static extern void Clear(int index=1);
       //===================================================================
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
           xktype  = comboBox1.Text;
           szComm    = textBox1.Text;
           szBaud = textBox2.Text;
 
           bool re = CreateMeter(xktype, 1, Convert.ToInt32(szComm), 
           Convert.ToInt32(szBaud), 'n', 8, 1);
           if (re)
           {
               label1.Text = "串口状态:打开成功";
           }
           else
           {
               label1.Text = "串口状态:打开不成功";
           }
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            ClosePort(1);
            label1.Text = "串口状态:串口关闭";
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            StringBuilder buff = new StringBuilder(255); 
            GetWeight(buff,1);
            label2.Text = buff.ToString();
            buff = null;//释放
 
            label5.Text = "缓冲区中数据量:"+ GetBuffLength().ToString();
 
            bool re = GetStatus();
            if (re)
                label4.Text = "通信状态:通信数据流正常";
            else
                label4.Text = "通信状态:通信数据流中断";
 
            byte[] data = new byte[1024];
            int c = GetSourceData(ref data[0],1);
            richTextBox1.Clear();
            for (int i = 0; i < c; i++)
            {
                richTextBox1.Text += data[i].ToString("X2") +" ";
            }
            data = null;
 
        }
 
        private void button3_Click(object sender, EventArgs e)
        {
            byte[] buff = new byte[1024];
            string a = "hello";
            BitConverter.ToString(buff);
            Write(ref buff[0], 1);
            buff = null;
        }
 
        private void button4_Click(object sender, EventArgs e)
        {
            timer1.Enabled = !timer1.Enabled;
            if (timer1.Enabled)
                button4.Text = "暂停";
            else
                button4.Text = "开始";
        }
 
    }

在XP上运行,请使用release方式编译发布,否则调用DLL中的函数时会报错!

















本文转自Chinayu201451CTO博客,原文链接:http://blog.51cto.com/9233403/2063081 ,如需转载请自行联系原作者



使用VS2015编译和调用动态链接库dll 1. 首先建工程,选择dll,记得勾上“导出符号” 后面不用自己搞那些宏定义会省事很多。 建立工程myDll,记得勾上“导出符号” 类型选择dll 2. IDE自动生成的代码已经把整个架构弄好了,其中和项目同名的.h和.cpp文件就是我们自己写代码的地方了。我想写的dll是导出一个类,在这里我就直接在它自动生成的CmyDll类上面改了。 myDll.h myDll.cpp 在mydll.h和mydll.cpp中给类添加成员函数 //mydll.h class MYDLL_API CmyDll { public: CmyDll(void); // TODO: 在此添加您的方法。 int myFunction(int a, int b); }; //mydll.cpp int CmyDll::myFunction(int a, int b) { return a*b; } 3.编译的时候我选择了release,这里可以用默认的debug也行 在mydll.h和mydll.cpp中给类添加成员函数 最后生成解决方案后产生的mydll.lib和mydll.dll就是我们需要的二进制文件了。lib文件是编译是要用的,而dll调用这个库的程序运行时需要的。 调用dll 1.重新建立一个工程 这回选择普通的控制台程序就行了。我建了个名为myDllCall的工程。 2.把库的头文件include进来,以及连接lib文件 其中 include进来的 myDll.h 和 **#pragma comment()**的lib根据自己的路径写。 #include "stdafx.h" #include "../../myDll/myDll/myDll.h" //头文件 #pragma comment(lib,"../../myDll/Release/myDll.lib") //调用自己写的外部库 #include int main() { CmyDll mydll; int a, b; std::cin >> a >> b; std::cout << mydll.myFunction(a, b) <> a >> b; std::cout << mydll.myFunction(a, b) << std::endl; return 0; } 3.dll放到可执行文件同一目录下面 刚刚的代码直接编译没问题,运行会报错. 直接编译没问题,运行会报错 原因是dll要和生成的可执行文件在同一个目录下,我把mydll.dll放进去之后就解决了。 我们成功的在自己的工程里调用了外部的类 可以看到我们成功的在自己的工程里调用了外部的类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值