zoukankan      html  css  js  c++  java
  • 为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.
    ", argv[1]);
        printf("argv[2] is %s.
    ", 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.
    ", 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.

  • 相关阅读:
    是否可能两个ETH私钥对应同一个地址
    使用 neon-wallet-db + neon-js + NEO-cli /rpc 搭建轻钱包服务端
    从源码看 angular/material2 中 dialog模块 的实现
    个人从源码理解JIT模式下angular编译AppModule的过程
    个人从源码理解angular项目在JIT模式下的启动过程
    使用angular的HttpClient搭配rxjs
    把angular项目整合到.net mvc中
    小程序开发整理
    ABC: Always Be Coding
    postgresql的psql常用命令-4
  • 原文地址:https://www.cnblogs.com/voipman/p/5284646.html
Copyright © 2011-2022 走看看