调用外部DLL,如:DelphiC++Java的DLL的调用方法,给出代码片段?
2011-07-25 16:06
1086 查看
//指示该属性化方法由非托管动态链接库 (DLL) 作为静态入口点公开。
假如没有路径的话,DllImport会按照顺序自动去寻找的地方:
1、exe所在目录 2、System32目录 3、环境变量目录
² Delphi_未测试
第一个参数是指要引用DLL的名字, 这个名字应该是个常量(否则会出错)。
CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet,则使用默认值 CharSet.Auto。
CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention,则使用默认值 CallingConvention.Winapi。
写一个函数就相应的应用起对应的DLL。
如何将Dephi的窗体显示在自己的页面中(且不能显示Delphi窗体的标题栏,实现无缝的结合)。 http://www.cnblogs.com/elivn/archive/2010/11/19/1881686.html Delphi一般类型对应如下:
Dephi-->C# intger -->int longint -->long pchar -->string THandle -->IntPtr Char[]-->string例:
Delphi DLL中的方法:
function GetXMLByNet(piChartType: integer; psXMLFileName: PChar; psPriChartFileName: PChar; psSecChartFileName: PChar; out psPriHotMsg: PChar; out psSecHotMsg: PChar): integer; stdcall;export;
调用:DrawChartFromDll.GetXMLByNet(m_chartType, _xmlFileName,...);² C++
类型对照:BSTR --------- StringBuilder LPCTSTR --------- StringBuilderLPCWSTR --------- IntPtr handle---------IntPtrhwnd-----------IntPtr char *----------stringint * -----------ref int int &-----------ref intvoid *----------IntPtr unsigned char *-----ref byteStruct需要在C#里重新定义一个StructCallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str);注意在每个函数的前面加上public static extern +返回的数据类型,如果不加public ,函数默认为私有函数,调用就会出错。 1. 数据类型转换问题 2. 指针或地址参数传送问题例如C++的原有函数是:int __stdcall FunctionName(unsigned char param1, unsigned short param2)其中的参数数据类型在C#中,必须转为对应的数据类型。如:[DllImport ( "COM DLL path/file" )]extern static int FunctionName ( byte param1 , ushort param2 );因为调用的是__stdcall函数,所以使用了P/Invoke的调用方法。其中的方法FunctionName必须声明为静态外部函数,即加上extern static声明头。我们可以看到,在调用的过程中,unsigned char变为了byte,unsigned short变为了ushort。变换后,参数的数据类型不变,只是声明方式必须改为.NET语言的规范。例:指针、引用类型int __stdcall FunctionName(unsigned char ¶m1, unsigned char *param2);
例:二维数组//C++编译的DLL里方法的声明: _declspec(dllexport) int device_EPC_fetch( char Ebuffer[50][33],int length,int device_id,int *tag_num);
² JAVA_未测试调用JAVA类,摘:http://zht1933.iteye.com/blog/607263//Java源代码: package com.zht; //c#中调用的类名//要调用的Java类 public class Test { //要调用的Java方法 public String returnString() { return "Hello, zht!"; }}一、将已经编译后的java中Class文件进行打包;打包命令JAR 如:将某目录下的所有class文件夹全部进行打包处理;使用的命令:jar cvf test.jar -C com/ .其中test.jar为要生成的jar包;com/ . 为指定的当前目录下的文件夹,该文件夹包括子文件夹及class文件; 二、到IKVM官方网站下载IKVM需要的组件 http://www.ikvm.net/ (或http://sourceforge.net/projects/ikvm/files/) a. kvm-0.42.0.3.zip b. ikvmbin-0.42.0.3.zip c. openjdk6-b16-stripped.zip http://hi.baidu.com/chen_claire/blog/item/0efbd1101971d205b8127b0f.html 文中提到 b\c中Zip没有使用到。 三、设置路径 解压ikvm-0.42.0.3.zip,并将%IKVM_HOME%\bin添加到path中。此处的%IKVM_HOME%是指解压后ikvm的主目录。四、将java的jar包转换为.dll控件 使用的命令:ikvmc -out:IKVM.dll test.jar其中IKVM.dll为将要生成的.dll控件文件名;test.jar为之前打包好的jar包文件。 五、在C#项目中添加所需的控件 1、新建一个C#.NET项目,首先添加一下必须的DLLs %IKVM_HOME%\bin\IKVM.OpenJDK.Core.dll %IKVM_HOME%\bin\IKVM.Runtime.dll %IKVM_HOME%\bin\IKVM.Runtime.JNI.dll 2、添加已生成的.dll文件 将之前生成好的.dll文件加载到C#项目中六、测试 在C#项目中使用java类,其方法同java。但对包的引用使用C#的语法usingusing com.zht; //与JAVA中的类名一致
² JAVA_WebService曾写与外公司的程序做过一次数据接口工作,当时那家公司提供了一个JAVA程序写的一个WebService地址:http://10.176.32.186/epm/services/ImeterData?wsdl方法://str xml格式的String类型public int saveMeterReadingDate(String str,String appNo,String operSystem)1、静态调用 先在项目中添加了一个WebService: WebReference.ImeterData
注:当时最大的问题是如何去取返回值,调用时发现有多个返回值。经过测试和网上查询,发现把返回值是写在方法参数内传入的。 2.动态调用(动态创建一个WebService)
System.Runtime.InteropServices.DllImportAttribute有时需要写上路径的如[DllImport(@"C:\OJ\Bin\Judge.dll")]这样指定DLL的绝对路径就可以正常装载。
假如没有路径的话,DllImport会按照顺序自动去寻找的地方:
1、exe所在目录 2、System32目录 3、环境变量目录
² Delphi_未测试
[ DllImport ( "WZFSE.dll" , CharSet = CharSet.Ansi ,
CallingConvention = CallingConvention.StdCall )] public static extern void InitDll(IntPtr handle, bool methodAddress);
第一个参数是指要引用DLL的名字, 这个名字应该是个常量(否则会出错)。
CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet,则使用默认值 CharSet.Auto。
CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention,则使用默认值 CallingConvention.Winapi。
写一个函数就相应的应用起对应的DLL。
[DllImport ( "user32.dll" , CharSet = CharSet.Ansi ,
CallingConvention = CallingConvention.StdCall )] public static extern void MoveWindow ( IntPtr handler , int x , int y ,
int width , int height , bool repaint );
如何将Dephi的窗体显示在自己的页面中(且不能显示Delphi窗体的标题栏,实现无缝的结合)。 http://www.cnblogs.com/elivn/archive/2010/11/19/1881686.html Delphi一般类型对应如下:
Dephi-->C# intger -->int longint -->long pchar -->string THandle -->IntPtr Char[]-->string例:
Delphi DLL中的方法:
function GetXMLByNet(piChartType: integer; psXMLFileName: PChar; psPriChartFileName: PChar; psSecChartFileName: PChar; out psPriHotMsg: PChar; out psSecHotMsg: PChar): integer; stdcall;export;
private class DrawChartFromDll { private const string _fileDll = @"Chart.dll"; //定义DLL文件名,此文件路径要加到系统Path中
[DllImport ( _fileDll , EntryPoint = "GetXMLByNet" , CharSet = CharSet.Ansi ,
CallingConvention =CallingConvention.StdCall )]
//调用非托管Dll,GetXMLByNet是ChartAccess.dll公开的函数名称 public static extern int GetXMLByNet ( int piChartType , string psXMLFileName ,
string psPriChartFileName , string psSecChartFileName , string psPriHotFileName , string psSecHotFileName ); }
调用:DrawChartFromDll.GetXMLByNet(m_chartType, _xmlFileName,...);² C++
类型对照:BSTR --------- StringBuilder LPCTSTR --------- StringBuilderLPCWSTR --------- IntPtr handle---------IntPtrhwnd-----------IntPtr char *----------stringint * -----------ref int int &-----------ref intvoid *----------IntPtr unsigned char *-----ref byteStruct需要在C#里重新定义一个StructCallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str);注意在每个函数的前面加上public static extern +返回的数据类型,如果不加public ,函数默认为私有函数,调用就会出错。 1. 数据类型转换问题 2. 指针或地址参数传送问题例如C++的原有函数是:int __stdcall FunctionName(unsigned char param1, unsigned short param2)其中的参数数据类型在C#中,必须转为对应的数据类型。如:[DllImport ( "COM DLL path/file" )]extern static int FunctionName ( byte param1 , ushort param2 );因为调用的是__stdcall函数,所以使用了P/Invoke的调用方法。其中的方法FunctionName必须声明为静态外部函数,即加上extern static声明头。我们可以看到,在调用的过程中,unsigned char变为了byte,unsigned short变为了ushort。变换后,参数的数据类型不变,只是声明方式必须改为.NET语言的规范。例:指针、引用类型int __stdcall FunctionName(unsigned char ¶m1, unsigned char *param2);
//在C#中对其进行调用的方法是: [DllImport("file")] extern static int FunctionName(ref byte param1, ref byte param2);
例:二维数组//C++编译的DLL里方法的声明: _declspec(dllexport) int device_EPC_fetch( char Ebuffer[50][33],int length,int device_id,int *tag_num);
//C#调用: [DllImport("MyFunDll.dll", EntryPoint = "device_EPC_fetch", CharSet = CharSet.Ansi)] public static extern int device_EPC_fetch( byte[,] arg1, int length, int id, ref int tag );
² JAVA_未测试调用JAVA类,摘:http://zht1933.iteye.com/blog/607263//Java源代码: package com.zht; //c#中调用的类名//要调用的Java类 public class Test { //要调用的Java方法 public String returnString() { return "Hello, zht!"; }}一、将已经编译后的java中Class文件进行打包;打包命令JAR 如:将某目录下的所有class文件夹全部进行打包处理;使用的命令:jar cvf test.jar -C com/ .其中test.jar为要生成的jar包;com/ . 为指定的当前目录下的文件夹,该文件夹包括子文件夹及class文件; 二、到IKVM官方网站下载IKVM需要的组件 http://www.ikvm.net/ (或http://sourceforge.net/projects/ikvm/files/) a. kvm-0.42.0.3.zip b. ikvmbin-0.42.0.3.zip c. openjdk6-b16-stripped.zip http://hi.baidu.com/chen_claire/blog/item/0efbd1101971d205b8127b0f.html 文中提到 b\c中Zip没有使用到。 三、设置路径 解压ikvm-0.42.0.3.zip,并将%IKVM_HOME%\bin添加到path中。此处的%IKVM_HOME%是指解压后ikvm的主目录。四、将java的jar包转换为.dll控件 使用的命令:ikvmc -out:IKVM.dll test.jar其中IKVM.dll为将要生成的.dll控件文件名;test.jar为之前打包好的jar包文件。 五、在C#项目中添加所需的控件 1、新建一个C#.NET项目,首先添加一下必须的DLLs %IKVM_HOME%\bin\IKVM.OpenJDK.Core.dll %IKVM_HOME%\bin\IKVM.Runtime.dll %IKVM_HOME%\bin\IKVM.Runtime.JNI.dll 2、添加已生成的.dll文件 将之前生成好的.dll文件加载到C#项目中六、测试 在C#项目中使用java类,其方法同java。但对包的引用使用C#的语法usingusing com.zht; //与JAVA中的类名一致
namespace KIVMTest { public partial class Form1 : Form { public Form1() { InitializeComponent();} private void Form1_Load(object sender, EventArgs e) { Test t = new Test();
string str = t.returnString();
MessageBox.Show(str); } } }
² JAVA_WebService曾写与外公司的程序做过一次数据接口工作,当时那家公司提供了一个JAVA程序写的一个WebService地址:http://10.176.32.186/epm/services/ImeterData?wsdl方法://str xml格式的String类型public int saveMeterReadingDate(String str,String appNo,String operSystem)1、静态调用 先在项目中添加了一个WebService: WebReference.ImeterData
/// 调用服务 并发送 bool SendData ( List<string> lstr ) { int iReturn; bool bReturnSpecified; WebReference.ImeterData id = new DataProvider_MiddleDB.WebReference.ImeterData ( ); id.Url ="http://10.176.32.186/epm/services/ImeterData?wsdl" ; id.saveMeterReadingDate ( lstr [ 0 ] , sAppNo , operSystem ,
out iReturn , out bReturnSpecified ); }
注:当时最大的问题是如何去取返回值,调用时发现有多个返回值。经过测试和网上查询,发现把返回值是写在方法参数内传入的。 2.动态调用(动态创建一个WebService)
public static object InvokeWebService ( string url , string classname , string methodname , object [ ] args ) { string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling"; #region 实例化服务 、调用服务方法 try { //获取WSDL WebClient wc = new WebClient ( ); url = url + "?wsdl"; //为从具有 System.String 指定的 URI 的资源下载的数据打开一个可读的流。 Stream stream = wc.OpenRead(url); //提供一种方法,以创建和格式化用于描述 XML Web services 的有效的 Web 服务描述语言 (WSDL) 文档文件, //该文件是完整的,具有适当的命名空间、元素和属性。无法继承此类。 ServiceDescription sd = ServiceDescription.Read ( stream ); //公开一种为 XML Web services 生成客户端代理类的方法。 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);// return mi.Invoke ( obj , args ); } catch ( Exception ex ) { throw new Exception ( ex.InnerException.Message , new Exception ( ex.InnerException.StackTrace ) ); } #endregion }
相关文章推荐
- 在java中调用c/c++代码的方法(jni)
- C/C++调用Java代码(属性和方法)
- 用Swig将c/c++程序转为java代码(使用swig实现java调用c、c++的方法)
- java加载外部文件数据到代码中:外部数据文件放到jar包中,调用方法getResourceAsStream
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- C++ 代码创建虚拟机调用java方法
- java加载外部文件数据到代码中:外部数据文件放到jar包中,调用方法getResourceAsStream
- 有关非Java代码(即Java调用C++中自然方法)的问题
- [2014.1.31] Eclipse、MinGW、JNI编写C++生成dll, Java端调用的完整示例(附java.lang.UnsatisfiedLinkError解决方法)
- Java调用C/C++代码-生成java调用的DLL
- [2014.1.31] Eclipse、MinGW、JNI编写C++生成dll, Java端调用的完整示例(附java.lang.UnsatisfiedLinkError解决方法)
- Java调用Delphi DLL(通过C++调用和直接调用两种方式)
- 入门: 使用JNI 从C++代码中调用Java的静态方法
- C/C++调用Java代码(属性和方法)
- JAVA通过JNI调用c++本地方法dll
- Java Native Interface(Java 调用Delphi、C、C++编写的DLL)
- 一种实现 Java调用C++的DLL的方法
- Delphi调用C++编写的动态链接库dll的方法
- 非托管C++代码调用C#编写的dll方法
- Eclipse、MinGW、JNI编写C++生成dll, Java端调用的完整示例(附java.lang.UnsatisfiedLinkError解决方法)