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. 小程序---电影商城---第三方组件 vant(vant weapp)

    小程序版本主页 https://youzan.github.io/vant-weapp/#/intro (1)创建项目描述文件 package.json ---鼠标右击 miniprogram  目录 ...

  2. python—mariadb自动部署主从

    import configparser import os def config_mariadb_yum(): exists = os.path.exists('/etc/yum.repos.d/ma ...

  3. 随机点名小程序--- -JAVA版本

    话不多少,直接上代码 一个能够直接运行的随机点名的小程序,一个界面化的小程序.望广大网友多多支持! 1.创建一个随机点名的类 public class ProcessRandomName { JFra ...

  4. ES6学习笔记01 -- 暂时性死区 ( temporal dead zone )

    参考文档: let 和 const 命令 - ECMAScript6入门  暂时性死区(temporal dead zone) 理解ES6中的TDZ(暂时性死区) ES6 中 let 暂时性死区详解 ...

  5. docker swarm 过滤器affinity 限制副本不会出现在同一个节点上

    affinity:container!=容器服务名称(可以是正则) 举个例子:stack_ds.yaml # cat stack_dsc.yaml version: '3.0' services: t ...

  6. Kubernetes概述

    1. Kubernetes是什么 Kubernetes是一个可移植的.可扩展的.用于管理容器化工作负载和服务的开源平台,它简化(促进)了声明式配置和自动化.它有一个庞大的.快速增长的生态系统.Kube ...

  7. heml基础笔记

    1.html:全名是超文本标记语言, hyper text mark language 2.html的标签 <p> :  <+和标签名 p+>结合而成. 每个标签都有自己的结束 ...

  8. (三)初识NumPy(数据CSV文件存取和多维数据的存取)

    本章主要介绍的是数据的CSV文件存取和多维数据的存取. 一.数据的CSV文件存取 1.CSV的写文件: np.savetxt(frame, array, fmt='%.18e', delimiter= ...

  9. JVM浅谈

    **前言** 由于先前也遇到过一些性能问题,OOM算是其中的一大类了.因此也对jvm产生了一些兴趣.自己对jvm略做了些研究.后续继续补充. **从oom引申出去** 既然说到oom,首先需要知道oo ...

  10. 【并发编程】Java对并发编程的支持历史

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文转载,原文请点击链接 本章主要对Java并发(Con ...