1. 包

很多功能存放在一起,定义为一个包,在iTcl(Incr TCL)之后,可以定义一个类,类可以放在一个包里面,包为一个独立的文件,可以为TCL文件,也可以为C/C++语言实现的动态库。

2. 代码结构

.
├── env.sh // 提供了 TCL_PACKAGE_ROOT 环境变量
├── lib
│ ├── init.tcl // tcl 执行时,source 该变量,提供auto_path寻找包的路径
│ ├── libpkg.so // C语言提供的包
│ ├── pkg.c // C代码,编译成libpkg.so
│ ├── pkgIndex.tcl // 包导出方法,该文件生成命令为tclsh环境中执行:pkg_mkIndex -- ./ *.so tools/*.tcl
│ └── tools
│ └── basic.tcl // Tcl提供的包
└── tst
└── test.tcl // 测试代码

3. 各文件内容

3.1. env.sh

#!/bin/bash

export TCL_PACKAGE_ROOT=$(pwd)

3.2. lib/init.tcl

if {[info exists env(TCL_PACKAGE_ROOT)] && (string trim $env(TCL_PACKAGE_ROOT) != "")} {
lappend auto_path $env(TCL_PACKAGE_ROOT)
} else {
puts "Need TCL_PACKAGE_ROOT env."
}

3.3. lib/pkg.c

// gcc -I/path/to/tcl/include -shared -o libpkg.so pkg.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tcl.h" int Pkg_Init(Tcl_Interp *Interp);
int Pkg_Unload(Tcl_Interp *Interp, int flags); int newcmd(int notUsed, Tcl_Interp *interp, int argc, char **argv)
{
if (argc != ) {
Tcl_SetResult(interp, "Usage::newcmd arg1", TCL_VOLATILE);
return TCL_ERROR;
} printf("argv[1] is %s.\n", argv[]);
Tcl_SetResult(interp, "This is my return", TCL_VOLATILE);
return TCL_OK;
} int Pkg_Init(Tcl_Interp *Interp)
{
if (Tcl_PkgProvide(Interp, "pkg", "1.0") == TCL_ERROR) {
return TCL_ERROR;
} Tcl_CreateCommand(Interp, "newcmd", (Tcl_CmdProc *)newcmd, , );
return TCL_OK;
} int Pkg_Unload(Tcl_Interp *Interp, int flags)
{
return TCL_OK;
}

3.4. lib/tools/basic.tcl

package provide Tools 1.0

namespace eval tools {
proc Test {args} {}
} proc tools::Test {args} {
puts "In tools::Test"
}

3.5. tst/test.tcl

#!/usr/bin/env tclsh

source $env(TCL_PACKAGE_ROOT)/lib/init.tcl

package require Tools
package require pkg tools::Test
set retStr [newcmd "hehe"]
puts "==$retStr=="

3.6. lib/pkgIndex.tcl

该文件通过如下方式自动生成:

$ cd lib/
$ tclsh
% pkg_mkIndex -- ./ tools/*.tcl *.so $ cat pkgIndex.tcl
# Tcl package index file, version 1.1
# This file is generated by the "pk_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script. It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands. When this
# script is sourced, the variable $dir must contain the
# full path name of this files's directory.
package ifneeded Tools 1.0 [list source [file join $dir tools/basic.tcl]]
package ifneeded pkg 1.0 [list load [file join $dir libpkg.so]]

4. 测试

$ source env.sh
$ cd tst/
$ chmod +x ./test.tcl
$ ./test.tcl
In tools::Test
argv[] is hehe
==This is my return==

[TimLinux] TCL 自定义包的更多相关文章

  1. 关于iOS和android自定义包的名字

    自定义包名的使用,android的包名和ios的包名都是你的自定义包名!如下以新浪微博SDK自定义包名示例:(官方没的,自己踩过坑,方便后来人吧) 相关技术文档:http://www.apicloud ...

  2. Python 调用自定义包

    创建包 # mkdir -p /python/utils # touch /python/utils/__init__.py # vi /python/utils/Log.pyimport timed ...

  3. Golang自定义包导入

    # 文件Tree project -/bin -/pkg -/src -main.go -/test -test1.go -test2.go main.go package main import ( ...

  4. go语言基础之包和自定义包与main包

    1.包 所有 Go 语言的程序都会组织成若干组文件,每组文件被称为一个包.这样每个包的代码都可以作为很小的复用单元,被其他项目引用. 一个包的源代码保存在一个或多个以.go为文件后缀名的源文件中,通常 ...

  5. Phyton自定义包导入。

    说明:同一个项目下的自定义包. 项目层次: 1:先建好项目Pybasestudty 2:建Python package,包名:pytestpk,__init__.py是建包时自动产生的文件. 3:在该 ...

  6. Go 使用自定义包(package)

    自定义包的分为两种: 1.同目录下的包: 2.不同目录下的包: *经测试,同目录下是不可以用不同包的文件的 同目录下的包: 不同文件中的变量和函数都可以直接访问 不同目录下的包: 1.把要在自定义包外 ...

  7. Go 自定义包引入报错

    配置文件 GO111MODULE=on 设置为on时,go命令行会使用modules,而一点也不会去GOPATH目录下查找.但自定义包在 $GOPATH/github.com/winyh/strrev ...

  8. python-sys模块、导入自定义包

    import问题:https://zhuanlan.zhihu.com/p/69099185 一.sys模块 sys模块是python自带模块,包含了与Python解释器和它的环境有关的函数.利用 i ...

  9. 9.5 自定义包和可见性 go mod

    the-way-to-go_ZH_CN/09.5.md at master · Unknwon/the-way-to-go_ZH_CN https://github.com/Unknwon/the-w ...

随机推荐

  1. css3 preserve-3d 的理解 注意IOS上的兼容

    css3 preserve-3d 的理解 <pre><!DOCTYPE html><html lang="en"> <head> & ...

  2. activmq点对点(简单写法)

    开发环境 我们使用的是ActiveMQ 5.11.1 Release的Windows版,官网最新版是ActiveMQ 5.12.0 Release,大家可以自行下载,下载地址. 需要注意的是,开发时候 ...

  3. 016.Kubernetes二进制部署所有节点kube-proxy

    一 部署 kube-proxy kube-proxy 运行在所有节点上,它监听 apiserver 中 service 和 endpoint 的变化情况,创建路由规则以提供服务 IP 和负载均衡功能. ...

  4. [LC]21题 Merge Two Sorted Lists (合并两个有序链表)(链表)

    ①英文题目 Merge two sorted linked lists and return it as a new list. The new list should be made by spli ...

  5. ubantu14.04安装storm伪分布式

    1.安装jdk 安装:sudo apt-get install openjdk-7-jdk 配置: 修改文件 sudo nano /etc/profile , 添加以下内容: 立即执行使之生效: 2. ...

  6. MemoryStream相关知识分享

    一.简单介绍一下MemoryStream MemoryStream是内存流,为系统内存提供读写操作,由于MemoryStream是通过无符号字节数组组成的,可以说MemoryStream的性能可以算比 ...

  7. Linux网络基本配置命令

    修改方法: 命令方式,大多是立即生效.临时有效: GUI图形方式, 修改配置文件,重启服务有效 1.修改主机名 hostname查看 hostname name临时修改 hostnamectl set ...

  8. 软件测试的原则,软件测试计划:5W1H

    1.测试应该尽早介入.        2.所有的测试都应追溯到用户需求.        3.程序员应该避免检查自己的程序.除了单元测试.因为程序员对于自己的作品,思维具有局限性.无法保证测试质量.交给 ...

  9. 移动端vue页面禁止移动/滚动

    当需要在移动端中禁止页面滚动,加入:@touchmove.prevent即可,例子如下 <template> <div @touchmove.prevent> <h3 c ...

  10. vim-plug 安装 jedi-vim

    安装: Plug 'davidhalter/jedi-vim' :PlugInstall 我就在配置文件里写了一个配置项 let g:jedi#use_tabs_not_buffers = 1 进入定 ...