首先在tcl中是没有办法直接调用C#编写的库函数的,因为这些函数都没有在tcl中进行注册。所以要调用C#编写的库函数,就必须对这些函数进行注册。由于这些函数都已经封装在dll动态库中,所以我们还是要通过一个中介来连接C#动态库和tcl。这就需要使用C++编写一个tcl的扩展库,在这个扩展库中调用C#动态库,并对其中的函数进行注册。主要有以下工作:
1、假设有一个现成的 由C#编写的一个mydll.dll 在类Class1下有个函数Mysum(int a,int b)
2、将vs2008 的配置改为C++的开发环境(看着习惯一些)
tools -> Import and Export Settings -> Reset All Settings
3、新建一个C++ 的 动态库,命名为usedll
由于我的是64位的操作系统,在这里将解决方案配置和解决方案平台改为Release x64
或者在 生成 -> 配置管理器 中修改 一样。同样的C#编写的mydll.dll也是在这样的平台下编译的。
4、将mydll.dll拷贝到新建的项目目录下(和文件在一个目录)
5、选择 公共语言运行支持/clr
在 项目 -> 属性 -> 配置属性 -> 常规
6、将mydll.dll添加到新引用
在 项目 -> 属性 -> 通用属性 -> 框架和引用
7、接下来就是包含tcl库和库函数
项目 -> 属性 -> 配置属性 -> C/C++下的 常规 附加包含目录中添加 D:\Tcl\include
项目 -> 属性 -> 配置属性 -> 链接器下的 常规 附加库目录添加 D:\Tcl\lib
项目 -> 属性 -> 配置属性 -> 链接器下的 输入 附加依赖项添加 tcl86.lib
项目 -> 属性 -> 配置属性 -> C/C++下的 预编译头 选择 不使用预编译头。
8、代码:
// usedll.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "tcl.h"
#include <iostream>
#include <tchar.h>
using namespace std;
using namespace mydll;
static int sum_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
int num[2];
if(objc != 3)
{
Tcl_WrongNumArgs(interp,1,objv,"arg1 arg2");
return TCL_ERROR;
}
for(int varindex = 1;varindex <= 2; varindex++)
{
if(Tcl_GetIntFromObj(interp,objv[varindex],&num[varindex - 1]) != TCL_OK)
{
Tcl_WrongNumArgs(interp,1,objv,"is Int Type");
return TCL_ERROR;
}
}
Class1 ^ addclass = gcnew Class1;
int tmp = addclass->Mysum(num[0],num[1]);
Tcl_SetObjResult(interp,Tcl_NewIntObj(tmp));
return 0;
}
extern "C" __declspec(dllexport) int Tclusedll_Init(Tcl_Interp *interp)
{
if(Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
if(Tcl_PkgProvide(interp, "usedll", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "tclsum", sum_Cmd, NULL, NULL);
return TCL_OK;
}
编译生成usedll.dll
9、在tcl中使用动态库
将usedll.dll和mydll.dll拷贝到Tcl安装目录的bin目录下
在tcl 命令行输入 load usedll.dll
输入 tclsum 2 3
输出 5 成功了
注意:步骤5 必须在步骤6之前,不然会找不到要添加的引用
如果是一个C++的应用程序调用C#动态库,上面的步骤相同(不需要的不做),在编译成功后可能无法运行,这时将新生成usedll.dll拷贝到exe目录就ok了。