您的位置:首页 > 编程语言 > Delphi

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

2011-07-25 16:06 1086 查看
//指示该属性化方法由非托管动态链接库 (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 --------- 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
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: