调用外部DLL,如:DelphiC++Java的DLL的调用方法,给出代码片段?

来源:互联网 发布:有益网络 编辑:程序博客网 时间:2024/06/05 17:08

//指示该属性化方法由非托管动态链接库 (DLL) 作为静态入口点公开。

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 --------- StringBuilder

LPCWSTR ---------  IntPtr        handle---------IntPtr

hwnd-----------IntPtr            char *----------string

int * -----------ref int         int &-----------ref int

void *----------IntPtr           unsigned char *-----ref byte

Struct需要在C#里重新定义一个Struct

CallBack回调函数需要封装在一个委托里,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 &param1, 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#的语法using

using 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        }


原创粉丝点击