C# 调用其他的动态库开发应注意的问题
1.背景
程序开发语言可以说是五花八门,这就引出了一个新问题 ,不同语言开发的系统进行对接时相关调用的问题。
下面我主要说一下我自己在做接口开发时遇到的问题及解决方法仅供参考,我使用的C#开发进行对接其他程序。
2.具体做法
首先,谈一下目前系统对接的几种常见对接方式。a.通过非托管的动态库dll文件导入。b.通过对方提供的COM组件调用。c.通过webService进行调用。
目前比较常用的就这个几种。下面一起看看都是如何具体调用实现以及遇到的问题。
a.通过非托管的动态库dll文件导入
此种方式在C#中的通用声明方式如下 。假如提供的dll 是InterfaceHN.dll 里面提供的方法 long init( char *Addr, int Port, char *Servlet)
[DllImport("InterfaceHN.dll")] 这里面还可以用 EntryPoint = "init", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true 属性指定更详细的信息 大家可以尝试一下 ,一般情况下只要指定函数入口点就行例如[DllImport("InterfaceHN.dll", EntryPoint = "init")]
public static extern Int32 init( [MarshalAs(UnmanagedType.VBByRefStr)] ref string addr, Int32 port, [MarshalAs(UnmanagedType.VBByRefStr)] ref string servlet);
public static extern Int32 init( [ StringBuilder addr, Int32 port, StringBuilder servlet);
在这种方式中,我以前遇到过的问题是内存保护,没有改方法 ,调用方法返回的值不正确等等问题。
这块就要注意参数的类型是不是两种语言都支持的,或者说是两种语言共有的 ,上面我就遇到过 ,文档上描述的是返回long 值 ,但是实际上返回的是Int32 导致这边出现内存保护提示。还有一点就是对于,带有参数返回值的这种情况 ,在C#一般字符串使用 StringBuilder 就可以 ,不行的话试一试[MarshalAs(UnmanagedType.VBByRefStr)] ref string paras 这种方式。出问题之后,首先自己检查参数类型对不对,一般对方是不会有问题的,但也不排除对方给的dll本身就有问题。
b.通过对方提供的COM组件调用。
这种方式比较简单,因为他本身就是一种接口标准。使用时只要注册它,然后添加引用把它引入你的程序。实例化相关的对象就可以使用了。
具体注册方法 :在系统运行窗口中输入regsvr32 +com组件的地址 例如regsvr32 D:公共程序集\RM.ReportEngine.dll 取消注册是在后面添加/u 开关。
c.通过webService进行调用。
此种调用也是目前比较方便流行的一种。只要给出服务的地址就可以进行 。但是有些环境你没法访问。例如vpn ,专网等等。这时就不能直接通过添加服务的方式进行访问了,但是可以通过得到他们的服务描述xml文件进行访问,如果还不行,就自己通过反射的方式建立客户端代理具体如下:
public class WebServiceHelper
{
#region InvokeWebService 动态调用web服务
/// <summary>
/// 动态调用WebService
/// </summary>
/// <param name="url">WebService地址</param>
/// <param name="methodname">方法名(模块名)</param>
/// <param name="args">参数列表</param>
/// <returns>object</returns>
public static object InvokeWebService(string url, string methodname, object[] args)
{
return WebServiceHelper.InvokeWebService(url, null, methodname, args);
}
/// <summary>
/// 动态调用WebService
/// </summary>
/// <param name="url">WebService地址</param>
/// <param name="classname">类名</param>
/// <param name="methodname">方法名(模块名)</param>
/// <param name="args">参数列表</param>
/// <returns>object</returns>
public static object InvokeWebService(string url, string classname, string methodname, object[] args)
{
try
{
string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
if ((classname == null) || (classname == ""))
{
classname = WebServiceHelper.GetWsClassName(url);
}
//获取WSDL
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(url + "?WSDL");
ServiceDescription sd = ServiceDescription.Read(stream);
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
CodeNamespace cn = new CodeNamespace(@namespace);
//生成客户端代理类代码
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
CSharpCodeProvider csc = new CSharpCodeProvider();
ICodeCompiler icc = csc.CreateCompiler();
//设定编译参数
CompilerParameters cplist = new CompilerParameters();
cplist.GenerateExecutable = false;
cplist.GenerateInMemory = true;
cplist.ReferencedAssemblies.Add("System.dll");
cplist.ReferencedAssemblies.Add("System.XML.dll");
cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
cplist.ReferencedAssemblies.Add("System.Data.dll");
//编译代理类
CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
if (true == cr.Errors.HasErrors)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
{
sb.Append(ce.ToString());
sb.Append(System.Environment.NewLine);
}
throw new Exception(sb.ToString());
}
//生成代理实例,并调用方法
System.Reflection.Assembly assembly = cr.CompiledAssembly;
Type t = assembly.GetType(@namespace + "." + classname, true, true);
object obj = Activator.CreateInstance(t);
System.Reflection.MethodInfo mi = t.GetMethod(methodname);
if (args == null)
return mi.Invoke(obj, null);
else
return mi.Invoke(obj, args);
}
catch (Exception ex)
{
throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));
}
}
private static string GetWsClassName(string wsUrl)
{
string[] parts = wsUrl.Split('/');
string[] pps = parts[parts.Length - 1].Split('.');
return pps[0];
}
#endregion
}
通过类WebServiceHelper这的方法 InvokeWebService(string url, string methodname, object[] args) 完成对方webservice 的调用。
一般在调用其他系统的东西时经常出现内存问题,找不到方法问题,无法连接问题,返回值不是值期望的值问题。这些问题只要仔细认真的分析
就可以解决,没有啥太难的东西。希望对你有帮助。
C# 调用其他的动态库开发应注意的问题的更多相关文章
- Android NDK开发及调用标准linux动态库.so文件
源:Android NDK开发及调用标准linux动态库.so文件 预备知识及环境搭建 1.NDK(native development Kit)原生开发工具包,用来快速开发C.C++动态库,并能自动 ...
- 关于C#调用非托管动态库方式的性能疑问
最近的项目中,因为一些原因,需要C#调用非托管(这里为C++)的动态库.网上喜闻乐见的方式是采用静态(DllImport)方式进行调用.偶然在园子里看到可以用动态(LoadLibrary,GetPro ...
- C#调用C/C++动态库 封送结构体,结构体数组
一. 结构体的传递 #define JNAAPI extern "C" __declspec(dllexport) // C方式导出函数 typedef struct { int ...
- linux c编程调用系统的动态库时,要使用dlopen等函数吗?
同问 linux c编程调用系统的动态库时,要使用dlopen等函数吗? 2012-11-27 21:55 提问者: hnwlxyzhl 我来帮他解答 满意回答 2012-12-07 09:08 li ...
- C#调用C/C++动态库,封装各种复杂结构体
C#调用C/C++动态库,封装各种复杂结构体. 标签: c++结构内存typedefc# 2014-07-05 12:10 6571人阅读 评论(1) 收藏 举报 分类: C(8) C#(6) ...
- cpp调用c的动态库
目录 cpp调用c的动态库 title: cpp调用c的动态库 date: 2019/11/22 20:34:29 toc: true --- cpp调用c的动态库 CPP文件里这么引用头文件即可 e ...
- 关于Android NDK中调用第三方的动态库
因为最近在整合Android 上RTSP播放器的网络库,因需要调用自己编译的网络库,调用一直出现问题,开始时是直接在Android.mk 中加入LOCAL_SHARED_LIBRARIES := li ...
- CWMP开源代码研究6——libcwmp动态库开发
原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 为了使程序具有通用性,便于扩展和维护.采用了"模块"插入的思想.将设备业务相 ...
- C#调用C/C++动态库 封送结构体,结构体数组
因为实验室图像处理的算法都是在OpenCV下写的,还有就是导航的算法也是用C++写的,然后界面部分要求在C#下写,所以不管是Socket通信,还是调用OpenCV的DLL模块,都设计到了C#和C++数 ...
随机推荐
- python内置函数(2)-递归与迭代
这篇文章简单介绍了迭代和递归的概念.两者的区别 什么是迭代: 迭代是重复反馈过程的活动,其目的通常是为了接近并达到所需的目标或结果.每一次对过程的重复被称为一次“迭代”,而每一次迭代得到的结果会被用来 ...
- Chessboard(规律)&&阿里巴巴和n个大盗(规律)
Chessboard Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- C#中Abstract和Virtual 【转】
http://www.cnblogs.com/blsong/archive/2010/08/12/1798064.html 在C#的学习中,容易混淆virtual方法和abstract方法的使用,现在 ...
- LSH算法原理
原始链接--http://www.jiahenglu.net/NSFC/LSH.html LSH(Location Sensitive Hash),即位置敏感哈希函数.与一般哈希函数不同的是位置敏感性 ...
- jQuery滑动选取数值范围插件
HTML 首先载入jQuery库文件以及jRange相关的css文件:jquery.range.css和插件:jquery.range.js <script src="jquery.j ...
- 【MFC学习笔记-作业5-小数据库】【单选框,复选框,滚动条,列表框】
界面已经实现完毕. 要完成的操作就是1.性别分组(2选1) 2.属性勾选 3.年龄通过滚动条调整 4.职称通过下方的列表框选择 5.输入姓名 6.存入左方的列表框 7.当选择左方列表框的人时,可以显示 ...
- 【枚举+贪心】【ZOJ3715】【Kindergarten Electiond】
题目大意: n 个人 在选取班长 1号十分想当班长,他已经知道其他人选择了谁,但他可以贿赂其他人改选他,问贿赂的最小值 ps.他自己也要投一个人 要处理一个问题是,他自己投谁 其实这个问题在这种局面下 ...
- C#运用实例.读取csv里面的词条,对每一个词条抓取百度百科相关资料,然后存取到数据库
第一步:首先需要将csv先装换成datatable,这样我们就容易进行对datatable进行遍历: /// 将CSV文件的数据读取到DataTable中 /// CSV文件路径 /// 返回读取了C ...
- SqlHelper数据库访问类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...
- 搜索+剪枝——运筹帷幄 (road.cpp)
运筹帷幄 (road.cpp) [题目描述] 刘邦军行至迷糊林,见其中瘴气围绕,又有青狼猛虎之兽,难于前行. 已知迷糊林是一个共有n个结点的图,点与点之间共有m条道路相连接,每条路有参数t,c,分别表 ...