专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »DotNet » vc编写dll:C#中加载自己编写的动态链接库(DLL) »正文

vc编写dll:C#中加载自己编写的动态链接库(DLL)

来源: 发布时间:星期四, 2009年2月12日 浏览:134次 评论:0


摘要 本文主要讲述如何在C#中逐步实现加载自己用C语言编写动态链接库以及在导入时如何进行C#和C语言数据类型匹配

关键词 C# C 动态链接库 加载 数据类型匹配



、发生背景

在开发新项目中使用了新语言开发C#和新技术方案WEB Service但是在新项目中些旧模块需要继续使用般是采用C或C或Delphi编写如何利用旧模块对于开发人员来说有 3种可用思路方法供选择:第、将C或C用C#彻底改写这样整个项目代码比较统维护也方便但是尽管微软以及某些书籍说C#和C如何接近但是改写起来还是很痛苦事情特别是C指针和内存操作;第 2、将C或C封装成COM在C#中COM比较方便只是在封装时需要处理C或C类型和COM类型的间转换也有些麻烦另外COM还需要注册注册次数多了又可能导致混乱;第 3、将C或C封装成动态链接库封装过程简单工作量不大因此我决定采用加载动态链接库思路方法实现于是产生了在C#中如何自定义动态链接库问题我在网上搜索相关主题发现系统API文章但是没有介绍说明如何解决此问题在MSDN上也没有相关详细介绍说明基于此我决定自己从简单出发逐步试验看看能否达到自己目标

(介绍说明点:我这里改写为什么很怕麻烦我改写代码是变长加密算法代码有600多行对算法本身不熟悉算法中指针和内存操作太多要想保证算法正确最可行思路方法就是少动代码否则只要有点点差错就不能肯定算法和以前兼容)



2、技术实现

下面看看如何逐步实现动态库加载类型匹配:



动态链接库导出定义这个不需要多说大家参考下面宏定义即可:

# LIBEXPORT_API extern \"C\" __declspec(dllexport)



我先从简单出发定义了个简单仅仅实现个整数加法求和:

LIBEXPORT_API mySum( a, b){ a+b;}



C#定义导入定义:

public RefComm

{

[DllImport(\"LibEncrypt.dll\", EntryPo=\" mySum \",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] public extern mySum ( a, b);

}



在C#中测试:

iSum= RefComm. mySum(2,3);

运行查看结果iSum为5正确步试验完成介绍说明在C#中能够自定义动态链接库



第 2步我定义了串操作(简单起见还是采用前面名)返回结果为串:

LIBEXPORT_API char *mySum(char *a,char *b){sprf(b,”%s”,a) a;}



C#定义导入定义:

public RefComm

{

[DllImport(\"LibEncrypt.dll\", EntryPo=\" mySum \",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] public extern mySum ( a, b);

}



在C#中测试:

strDest=””;

strTmp= RefComm. mySum(“12345”, strDest);

运行查看结果strTmp为“12345”但是strDest为空



我修改动态链接库实现返回结果为串b:

LIBEXPORT_API char *mySum(char *a,char *b){sprf(b,”%s”,a) b;}



修改C#导入定义将串b修改为ref方式:

public RefComm

{

[DllImport(\"LibEncrypt.dll\", EntryPo=\" mySum \",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] public extern mySum ( a, ref b);

}

在C#中再测试:

strDest=””;

strTmp= RefComm. mySum(“12345”, ref strDest);

运行查看结果strTmp和strDest均不对含不可见



再修改C#导入定义将CharSet从Auto修改为Ansi:

public RefComm

{

[DllImport(\"LibEncrypt.dll\", EntryPo=\" mySum \",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] public extern mySum ( a, b);

}

在C#中再测试:

strDest=””;

strTmp= RefComm. mySum(“12345”, ref strDest);

运行查看结果strTmp为“12345”但是串strDest没有赋值第 2步实现返回串但是在出口参数中没能进行输出



再次修改C#导入定义将串b修改为引用(ref):

public RefComm

{

[DllImport(\"LibEncrypt.dll\", EntryPo=\" mySum \",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] public extern mySum ( a, ref b);

}

运行时失败不能继续执行



第 3步修改动态链接库实现将b修改为双重指针:

LIBEXPORT_API char *mySum(char *a,char **b){sprf((*b),”%s”,a) *b;}



C#导入定义:

public RefComm

{

[DllImport(\"LibEncrypt.dll\", EntryPo=\" mySum \",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] public extern mySum ( a, ref b);

}



在C#中测试:

strDest=””;

strTmp= RefComm. mySum(“12345”, ref strDest);

运行查看结果strTmp和strDest均为“12345”正确第 3步实现了出口参数正确输出结果



第 4步修改动态链接库实现实现整数参数输出:

LIBEXPORT_API mySum( a, b, *c){ *c=a+b; *c;}



C#导入定义:

public RefComm

{

[DllImport(\"LibEncrypt.dll\", EntryPo=\" mySum \",CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] public extern mySum ( a, b,ref c);



}



在C#中测试:

c=0;

iSum= RefComm. mySum(2,3, ref c);

运行查看结果iSum 和c均为5正确



经过以上几个步骤试验基本掌握了如何定义动态库以及如何在C#定义导入有此基础很快我实现了变长加密在C#中至此目标实现



3、结论

在C#中C编写动态链接库如果需要出口参数输出则需要使用指针对于则需要使用双重指针对于C#导入定义则需要使用引用(ref)定义

对于返回值C#导入定义和C动态库申明定义需要保持否则会出现失败

定义导入时定注意CharSet和CallingConvention参数否则导致失败或结果异常

运行时动态链接库放在C#目录下即可我这里是个C#动态链接库两个动态链接库就在同个目录下运行

0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: