核心原理:为什么能调用?
易语言之所以能调用 C 的 DLL,是因为它们都遵循 Windows API 调用约定,本质上是操作系统提供的标准机制。

- 编译为机器码:无论是用 C 语言(如 Visual C++)还是易语言编写的程序,最终都会被编译成 Windows 操作系统能够理解的机器码(
.exe或.dll)。 - 函数入口点:DLL 文件内部包含一个个的函数,这些函数在编译时会被赋予一个标准的“入口点”或“导出名”(Export Name),当外部程序(如易语言程序)想要调用这个函数时,操作系统会根据这个导出名找到函数在内存中的地址,然后跳转到该地址执行代码。
- 参数传递:调用函数时,参数的传递方式(通过堆栈还是寄存器)和清理方式由调用约定决定,C 语言默认使用
__cdecl,而 Windows API 使用__stdcall,易语言在调用 DLL 时,默认使用__stdcall,这与 Windows API 完全兼容,所以可以无缝调用。
DLL 就像一个“工具箱”,易语言是“使用者”,C 语言是“制造者”,只要工具箱里的工具(函数)有明确的规格(参数和返回值类型),使用者就能正确地使用它们。
准备工作:编写 C 语言 DLL
我们将使用 Visual Studio 2025/2025 来创建一个简单的 DLL。
创建 DLL 项目
- 打开 Visual Studio。
- 选择“创建新项目”。
- 搜索并选择 “动态链接库 (DLL)” 项目模板,然后点击“下一步”。
- 给项目命名,
MyCLib,并选择一个位置,然后点击“创建”。
编写 C 代码
打开 MyCLib.h 和 MyCLib.cpp 文件,编写如下代码:
MyCLib.h (头文件)

// 为了防止头文件被重复包含
#pragma once
// 使用 extern "C" 来告诉 C++ 编译器,使用 C 语言的命名规则来导出函数
// 这样可以避免 C++ 的名称修饰(Name Mangling),让易语言能找到正确的函数名
#ifdef __cplusplus
extern "C" {
#endif
// 导出函数声明
// __declspec(dllexport) 表示这个函数要从 DLL 中导出出来
// __stdcall 是标准的调用约定,与易语言兼容
__declspec(dllexport) int __stdcall Add(int a, int b);
__declspec(dllexport) const char* __stdcall GetHelloMessage();
__declspec(dllexport) void __stdcall PrintArray(int* arr, int size);
#ifdef __cplusplus
}
#endif
MyCLib.cpp (源文件)
#include "MyCLib.h"
#include <stdio.h> // 用于 printf
// 函数定义
int __stdcall Add(int a, int b) {
return a + b;
}
const char* __stdcall GetHelloMessage() {
// 注意:在 DLL 中返回静态字符串或堆上分配的内存是安全的
// 不要返回局部变量的地址,因为函数结束后局部变量会被销毁
return "Hello from C DLL!";
}
void __stdcall PrintArray(int* arr, int size) {
printf("C DLL received an array: [");
for (int i = 0; i < size; i++) {
printf("%d", arr[i]);
if (i < size - 1) {
printf(", ");
}
}
printf("]\n");
}
编译 DLL
- 在 Visual Studio 中,选择 生成 -> 生成解决方案 (或按 F7)。
- 编译成功后,你可以在项目的
x64\Debug(或x64\Release) 文件夹下找到生成的 DLL 文件:MyCLib.dll。 - 重要:你还需要将
MyCLib.h头文件复制出来,虽然易语言不直接用它,但它能帮你清晰地知道 DLL 里有哪些函数、参数和返回值类型。
在易语言中调用 DLL
我们打开易语言,来调用刚刚生成的 MyCLib.dll。
新建易语言程序
- 打开易语言,创建一个“Windows 窗口程序”。
- 在窗口上放置几个控件:
- 一个“编辑框”,变量名为
编辑框_数值1为10。 - 另一个“编辑框”,变量名为
编辑框_数值2为20。 - 一个“按钮”,标题为“调用 Add 函数”,变量名为
按钮_调用加法。 - 一个“标签”,变量名为
标签_结果,用于显示加法结果。 - 一个“按钮”,标题为“调用 GetHelloMessage”,变量名为
按钮_调用字符串。 - 一个“标签”,变量名为
标签_消息,用于显示字符串。 - 一个“按钮”,标题为“调用 PrintArray”,变量名为
按钮_调用数组。 - 一个“标签”,变量名为
标签_数组信息,用于显示调用结果。
- 一个“编辑框”,变量名为
声明外部 DLL 函数
这是最关键的一步,在易语言代码窗口的“程序集”下,点击“外部DLL命令”,然后点击“新建”。
使用“查看DLL命令”工具(推荐)

-
点击工具栏上的“查看DLL命令”按钮。
-
在弹出的窗口中,点击“选择DLL”,找到你刚才生成的
MyCLib.dll文件。 -
DLL 文件加载后,它会自动扫描并列出所有导出的函数。
-
选中
Add函数,点击“添加”。 -
在右侧的“定义”窗口中,你需要设置参数和返回值的类型:
- 返回值类型:选择“整数”。
- 参数1:名称可以填
a,类型选择“整数”。 - 参数2:名称可以填
b,类型选择“整数”。
-
点击“确定”,易语言会自动生成代码。
-
用同样的方法添加
GetHelloMessage和PrintArray函数。GetHelloMessage:- 返回值类型:文本
- 无参数
PrintArray:- 返回值类型:无返回值
- 参数1:名称
arr,类型选择整数型,并勾选“指针”或“地址”。 - 参数2:名称
size,类型选择“整数”。
手动编写声明代码
如果你没有“查看DLL命令”工具,或者想手动控制,可以直接在代码编辑器中输入:
.版本 2
.程序集 窗口程序集_启动窗口
.子程序 __启动窗口_创建完毕, , 公开
.局部变量 a, 整数)
.局部变量 b, 整数)
.局部变量 p, 整数型) ' 用于接收数组指针
.(真)
' --- 声明外部 DLL 函数 ---
.子程序 Add, 整数, 公开, "MyCLib.dll"
.参数 a, 整数
.参数 b, 整数
.子程序 GetHelloMessage, 文本, 公开, "MyCLib.dll"
' 无参数
.子程序 PrintArray, , 公开, "MyCLib.dll"
.参数 arr, 整数型, , 指针 ' 声明为指针类型
.参数 size, 整数
.如果结束
注意:.版本 2 是必须的,它让易语言支持更现代的语法,特别是“指针”类型的参数。
编写按钮事件代码
为按钮编写点击事件。
“调用 Add 函数”按钮的代码:
.版本 2
.程序集 窗口程序集_启动窗口
.子程序 _按钮_调用加法_被单击
.局部变量 结果, 整数)
' 从编辑框获取数值
结果 = 编辑框_数值1.取文本到数值 (真)
.(结果 = 0, 真)
信息框 (“数值1输入无效!”, 0, , )
返回 ()
.否则
.局部变量 a, 整数)
a = 结果
.如果结束
结果 = 编辑框_数值2.取文本到数值 (真)
.(结果 = 0, 真)
信息框 (“数值2输入无效!”, 0, , )
返回 ()
.否则
.局部变量 b, 整数)
b = 结果
.如果结束
' 调用 C DLL 中的 Add 函数
结果 = Add (a, b)
' 显示结果
标签_结果.内容 = “计算结果: ” = 到文本 (结果)
“调用 GetHelloMessage”按钮的代码:
.版本 2 .程序集 窗口程序集_启动窗口 .子程序 _按钮_调用字符串_被单击 .局部变量 消息, 文本) ' 调用 C DLL 中的 GetHelloMessage 函数 消息 = GetHelloMessage () ' 显示消息 标签_消息.内容 = 消息
“调用 PrintArray”按钮的代码:
.版本 2 .程序集 窗口程序集_启动窗口 .子程序 _按钮_调用数组_被单击 .局部变量 数组数据, 整数, , "0,1,2,3,4") .局部变量 数组大小, 整数) .局部变量 p, 整数型) ' 指针变量 ' 准备数据 数组大小 = 取数组成员数 (数组数据) ' 关键步骤:获取数组的内存地址(指针) p = 取数据地址 (数组数据) ' 调用 C DLL 中的 PrintArray 函数,并传递指针和大小 PrintArray (p, 数组大小) ' 告诉用户调用成功 标签_数组信息.内容 = “已成功向 C DLL 发送数组,请查看易语言控制台输出。” ' 在易语言控制台打印信息,方便调试 输出调试文本 (“易语言:已调用 PrintArray 函数”)
运行和测试
- 按
F5运行易语言程序。 - 点击“调用 Add 函数”按钮,
标签_结果应该会显示30。 - 点击“调用 GetHelloMessage”按钮,
标签_消息应该会显示Hello from C DLL!。 - 点击“调用 PrintArray”按钮,
标签_数组信息会出现提示。请回到 Visual Studio 窗口,你会看到调试控制台(Output 窗口)打印出了:C DLL received an array: [0, 1, 2, 3, 4]这证明了 C 函数成功接收并处理了从易语言传递过来的数组数据。
常见问题与解决方法
-
“无法找到入口点”或“找不到指定的模块”
- 原因:最常见的原因是函数名或调用约定不匹配。
- 函数名:确保 C 函数声明使用了
extern "C",并且易语言声明的函数名与 DLL 中的导出名完全一致(区分大小写),你可以使用 Dependency Walker (depends.exe) 或 Process Monitor (ProcMon) 等工具来查看 DLL 中实际导出的函数名。 - 调用约定:C 函数必须是
__stdcall,与易语言默认的调用约定一致,C 函数是__cdecl,易语言调用时可能会出错。
- 函数名:确保 C 函数声明使用了
- 解决:检查函数名拼写、大小写,以及 C 函数的
__declspec和__stdcall声明。
- 原因:最常见的原因是函数名或调用约定不匹配。
-
“内存访问违规”或“程序崩溃”
- 原因:通常是由于参数传递错误导致的。
- 类型不匹配:易语言传递的参数类型(如“整数”是 4 字节)与 C 函数期望的类型(如
long可能是 8 字节)不一致。 - 指针错误:对于指针或数组参数,易语言必须使用“取数据地址”来获取内存地址,并正确声明为“指针”类型,传递错误的地址或无效的指针会导致程序崩溃。
- 字符串处理:C 函数返回的字符串最好是静态分配的(如
char* s = "hello";),如果是在函数内部动态分配的内存(malloc),易语言使用完后需要想办法释放,否则会造成内存泄漏,对于 DLL 返回的字符串,易语言通常只能读取,不能修改。
- 类型不匹配:易语言传递的参数类型(如“整数”是 4 字节)与 C 函数期望的类型(如
- 解决:仔细核对每个参数在 C 和易语言中的类型定义,对于指针,确保传递的是有效的地址。
- 原因:通常是由于参数传递错误导致的。
-
DLL 文件找不到
- 原因:易语言程序运行时找不到
MyCLib.dll文件。 - 解决:将
MyCLib.dll文件复制到以下任一位置:- 易语言程序所在的同一目录下(最常用)。
C:\Windows\System32目录下(不推荐,可能导致系统混乱)。- 在 Visual Studio 中设置 DLL 的输出目录,使其与易语言的
exe文件放在一起。
- 原因:易语言程序运行时找不到
调用 C DLL 的核心流程可以总结为:
- C 端:
- 使用
__declspec(dllexport)和__stdcall关键字导出函数。 - 使用
extern "C"避免名称修饰。
- 使用
- 易语言端:
- 使用“外部DLL命令”或手动代码,声明与 C 函数参数和返回值类型对应的易语言子程序。
- 对于指针/数组参数,使用“取数据地址”并声明为“指针”类型。
- 调用声明的子程序,并传递正确的参数。
遵循以上步骤和原则,你就可以成功地在易语言中调用绝大多数用 C 语言编写的 DLL 文件了。
