为Tcl编写C的扩展库
Tcl是一个比较简洁的脚本语言,官方地址 http://www.tcl.tk.
tcl脚本加载C实现的动态库非常方便。
1. 为Tcl编写一个用C实现的扩展函数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tcl.h> extern "C" {
// extern for C++.
int Myimpltcl_Init(Tcl_Interp *Interp);
int Myimpltcl_Unload(Tcl_Interp *Interp);
} int Action_FuncA(int notUsed, Tcl_Interp *interp, int argc, char **argv) {
if (argc != 3) {
// check args, same as main function args.
Tcl_SetResult(interp, "Usage::Action_FuncA arg1 arg2",
TCL_VOLATILE);
return TCL_ERROR;
}
printf("argv[1] is %s.\n", argv[1]);
printf("argv[2] is %s.\n", argv[2]);
// return string.
Tcl_SetResult(interp, "return of Action_FuncA", TCL_VOLATILE);
return TCL_OK;
} int Action_FuncB(int notUsed, Tcl_Interp *interp, int argc, char **argv) {
if (argc != 2) {
// check args, same as main function args.
Tcl_SetResult(interp, "Usage::Action_FuncB arg1",
TCL_VOLATILE);
return TCL_ERROR;
}
printf("argv[1] is %s.\n", argv[1]);
// return string.
Tcl_SetResult(interp, "return of Action_FuncB", TCL_VOLATILE);
return TCL_OK;
} int Myimpltcl_Init(Tcl_Interp *Interp) {
// initialize operation.
Tcl_CreateCommand (Interp, "Action_FuncA", (Tcl_CmdProc *)Action_FuncA, 0, 0);
Tcl_CreateCommand (Interp, "Action_FuncB", (Tcl_CmdProc *)Action_FuncB, 0, 0);
return TCL_OK;
} int Myimpltcl_Unload(Tcl_Interp *Interp, int flags) {
// destroy operation.
return TCL_OK;
}
分析:
tcl.h是加载tcl需要头文件。
初始化函数 Myimpltcl_Init
使用Tcl_CreateCommand函数创建一个可以在tcl脚本中调用的函数,函数的实现指向C实现的函数。
| 创建方法 | Tcl中可以调用的函数名称 | C中实现的函数名称 |
Tcl_CreateCommand |
Action_FuncA |
int Action_FuncA(int notUsed, Tcl_Interp *interp, int argc, char **argv) |
Tcl_CreateCommand |
Action_FuncB |
int Action_FuncB(int notUsed, Tcl_Interp *interp, int argc, char **argv) |
退出函数 Myimpltcl_Unload
tcl卸载动态库时会调用的函数,用于是否内存和其他的资源。
2. 编写Makefile文件
CC = gcc -g -O3 -w
SHARED_FLAG = -fPIC -shared
PROJECT = libmyimpltcl.so INC = -I./
INC += -I$(TCL_HOME)/include
LIB = -L$(TCL_HOME)/lib -ltcl8.5 all : $(PROJECT) $(PROJECT) :
$(CC) myimpltcl.cpp ${SHARED_FLAG} -o $(PROJECT) $(INC) $(LIB) clean:
rm -rf *.o *.a *.so
分析:
生成的动态库名称必须是libmyimpltcl.so,为什么呢?
Tcl加载C编写的so库的规则是。
void *handle = dlopen("libmyimpltcl.so", RTLD_NOW | RTLD_GLOBAL);
将so库的名称去掉lib前缀
libmyimpltcl.so
把去掉前缀的第一个字母变成大写并增加后缀_Init
myimpltcl --> Myimpltcl_Init
拼接成新的字符串作用动态库的入库函数,用dlsym系统调用得到so中的C函数地址,并执行
dlsym(handle, "Myimpltcl_Init");
3. 测试
[user@host tcl]# tclsh
% load libmyimpltcl.so
% # 加载编译好的so库
% info loaded
% # 查看加载过的库信息
{libmyimpltcl.so Myimpltcl}
% set ret [Action_FuncA param1 param2]
% # 调用so中的C函数Action_FuncA
argv[1] is param1.
argv[2] is param2.
return of Action_FuncA
% puts $ret
return of Action_FuncA
% set retB [Action_FuncB 123]
% # 调用so中的C函数Action_FuncB
argv[1] is 123.
return of Action_FuncB
% puts $retB
return of Action_FuncB
Done.
为Tcl编写C的扩展库的更多相关文章
- 如何编写自己的Arduino库?
一开始写Arduino 的时候很不习惯,没有main函数,因为好多东西都被隐藏了.一直想搞清楚,以便编写自己的库文件.于是研究一下午,下面是一些总结. Arduino工程的初步认识 一.目录规范 当你 ...
- PHP扩展编写、PHP扩展调试、VLD源码分析、基于嵌入式Embed SAPI实现opcode查看
catalogue . 编译PHP源码 . 扩展结构.优缺点 . 使用PHP原生扩展框架wizard ext_skel编写扩展 . 编译安装VLD . Debug调试VLD . VLD源码分析 . 嵌 ...
- php笔记08:数据库编程---使用php的MySQL扩展库操作MySQL数据库
1.使用php的MySQL扩展库操作MySQL数据库: php有3种方式操作MySQL数据库 (1)mysql扩展库 (2)mysqli扩展库 (3)pdo mysql扩展库与mysql数据库 ...
- Python和C++的混合编程(使用Boost编写Python的扩展包)
想要享受更轻松愉悦的编程,脚本语言是首选.想要更敏捷高效,c++则高山仰止.所以我一直试图在各种通用或者专用的脚本语言中将c++的优势融入其中.原来贡献过一篇<c++和js的混合编程>也是 ...
- 『Python CoolBook』C扩展库_其一_用法讲解
不依靠其他工具,直接使用Python的扩展API来编写一些简单的C扩展模块. 本篇参考PythonCookbook第15节和Python核心编程完成,值得注意的是,Python2.X和Python3. ...
- JavaScript学习总结(十四)——JavaScript编写类的扩展方法
在JavaScript中可以使用类的prototype属性来扩展类的属性和方法,在实际开发当中,当JavaScript内置的那些类所提供的动态 ...
- 使用php的mysqli扩展库操作mysql数据库
简单介绍mysqli: 1.mysqli(mysql improve mysql扩展库的增强版) mysql扩展库和mysqli扩展库的区别 1.mysqli的稳定性 安全性 和 执行效率有所提高 ...
- scrapy进阶-编写中间件和扩展
中间件: 主要讨论的是下载中间件,明确一下顺序: download_middlewares --> server.url ---> spider_middleware 我主 ...
- php数据库编程---mysqli扩展库
1,mysqli扩展库允许我们访问MySQL数据库,并对MySql数据库进行curd操作.Mysqli扩展库比mysql扩展库加强了. 2,mysqli扩展库和mysql扩展库的比较 (1) mysq ...
随机推荐
- springboot Serving Web Content with Spring MVC
Serving Web Content with Spring MVC This guide walks you through the process of creating a "hel ...
- BZOJ 3524: [Poi2014]Couriers [主席树]
3524: [Poi2014]Couriers Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1892 Solved: 683[Submit][St ...
- 洛谷P1288 取数游戏II[博弈论]
题目描述 有一个取数的游戏.初始时,给出一个环,环上的每条边上都有一个非负整数.这些整数中至少有一个0.然后,将一枚硬币放在环上的一个节点上.两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流 ...
- String,StringBuffer,StringBuilder的区别
public static void main(String[] args) { String str = new String("hello...."); StringBuffe ...
- 写Java也得了解CPU--伪共享
第一次接触伪共享的概念,是在马丁的博客上:而ifeve也把这一系列博文翻译整理好了.概读了几次,感觉到此概念的重要.因此有了这个系列的第二篇读后总结. 1. 什么是伪共享(False sharing) ...
- tensorflow学习笔记三:实例数据下载与读取
一.mnist数据 深度学习的入门实例,一般就是mnist手写数字分类识别,因此我们应该先下载这个数据集. tensorflow提供一个input_data.py文件,专门用于下载mnist数据,我们 ...
- .net线程池
线程池的作用线程池,顾名思义,线程对象池.Task和TPL都有用到线程池,所以了解线程池的内幕有助于你写出更好的程序.由于篇幅有限,在这里我只讲解以下核心概念: 线程池的大小 如何调用线程池添加任务 ...
- RSA加密算法的java实现
package rsa; import java.security.*;import java.security.interfaces.*;import javax.crypto.*; public ...
- C/C++实践笔记 004
转义字符 #define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h> void main1() { c ...
- HTML5 File API — 让前端操作文件变的可能
前言 在 HTML5 File API 出现之前,前端对于文件的操作是非常有局限性的,大多需要配合后端实现.出于安全角度考虑,从本地上传文件时,代码不可能获取文件在用户本地的地址,所以纯前端不可能完成 ...