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++数 ...
随机推荐
- 【机房系统知识小结点系列】之遍历窗体中的控件,判断Text是否为空?
做机房系统时,几乎每个窗体中都会用到判断界面中的控件是否为空的情景.我们曾经是这样走来的: 第一版: 好处:对窗体界面中的Text等控件,逐一做判断,当用户输入某一项为空的时候,会议弹出框的形式,告诉 ...
- android卸载反馈实现
博客原地址:http://blog.csdn.net/wang_shaner/article/details/41543787 实现原理 fork分叉函数 fork分叉(分裂)函数可以创建一个新进程, ...
- myeclipse中自己手动配置maven
第一步,配置myeclipse的jdk,因为myeclipse默认的是运行在jre之上,而maven是在jdk之上 第二步,配置maven:
- ThInkPHP中的常量
除了常规变量的输出外,模板引擎还支持系统变量和系统常量.以及系统特殊变量的输出.它们的输出不需要事先赋值给某个模板变量.系统变量的输出必须以$Think.打头,并且仍然可以支持使用函数.常用的系统变量 ...
- AndroidUI--SlidingMenu使用例子
SlidingMenu简介: SlidingMenu的是一种比较新的设置界面或配置界面效果,在主界面左滑或者右滑出现设置界面,能方便的进行各种操作.目前有大量的应用都在使用这一效果.如Evernote ...
- WPF基础
1.Sender 指的是被点击的控件.默认为object类. private void btnc1_Click(object sender, RoutedEventArgs e) { Button b ...
- Windows中进程的内存结构
基础知识: 栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表.允许插入或删除操作的一端称为栈顶,另一端称为栈底,对栈的插入和删除操作被称为入栈和出栈. 有一组CPU指令可以实现对进程 ...
- OpenGL鼠标旋转图像
(鼠标旋转功能) #include <iostream> using namespace std; #include<gl/glut.h> GLfloat transx,tra ...
- 表单提交中get与post的区别
在Form里面,可以使用post也可以使用get.它们都是method的合法取值. 1. get是从服务器上获取数据,post是向服务器传送数据. 2. get是把参数数据队列加到提交表单的ACT ...
- Android 动画小知识点
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="h ...