GVKun编程网logo

vb.net 调用Delphi dll问题(vb调用dll实例)

6

最近很多小伙伴都在问vb.net调用Delphidll问题和vb调用dll实例这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展(Delphi)使用函数指针参数调用DLL、.net调

最近很多小伙伴都在问vb.net 调用Delphi dll问题vb调用dll实例这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展(Delphi)使用函数指针参数调用DLL、.net 调用delphi 的DLL、C# 调用 Delphi DLL、C# 调用delphi编写的dll等相关知识,下面开始了哦!

本文目录一览:

vb.net 调用Delphi dll问题(vb调用dll实例)

vb.net 调用Delphi dll问题(vb调用dll实例)

前一段项目,要调用第三方的接口实现医保卡读取和医保信息上传.遇到一个太诡异的问题.

不管怎么调用使用显示"出错误尝试读取或写入受保护的内存。这通常指示其他内存已损坏。" 问题.

对于Delphi中的Pchar 类型的 使用(Byval StringBuilder…定义

如:

_
Public Shared Function Test(ByVal p As StringBuilder,ByRef d As Single) As Integer

End Function

_
Public Shared Function Freadcard(ByVal iprescno As Integer,ByVal Icardtype As Integer,……

这样Delphi 对 stringBuilder 的值改变才能被取出来. 这样避免乱码的问题.

(Delphi)使用函数指针参数调用DLL

(Delphi)使用函数指针参数调用DLL

我坚持调用外部DLL并将函数(指针)作为参数传递.
我最近有一些不同的问题,传递一些参数到DLL,你帮助.
希望,有人知道如何做到这一点….

这是DLL(cpp)中需要从Delphi调用的函数声明:

typedef void (*PTR_Allocate)(char**,unsigned long*);
typedef void (*PTR_Deallocate)(char*);

extern "C" export_dll_function void SetAllocateFunction(PTR_Allocate);
extern "C" export_dll_function void SetDeallocateFunction(PTR_Deallocate);

void Allocate(char** pbuffer,unsigned long* psize)
{
    *psize = *psize * 2;
    *pbuffer = new char[*psize];
}

void Deallocate(char* buffer)
{
    delete[] buffer;
}

能帮助我在Delphi(7)中重写这个吗?

这是我尝试过的,它抛出一个异常(“外部异常”):

type
   PByte = ^TByte;
   TByte = array of byte;
   TFunc = function(var pbuffer: PByte; var psize: Cardinal): integer; cdecl;
   Procedure _SetAllocateFunction(var f: TFunc); cdecl;

implementation

function Allocate(var pbuffer: PByte; var psize: Cardinal): Integer; cdecl;
begin
  psize := psize * 2;
  GetMem(pbuffer,psize);
end;

   var Func: TFunc;
   Func := @Allocate;
   _SetAllocateFunction(Func);

非常感谢你 !

解决方法

如果您不确定自己在做什么,请始终使用最直接的翻译.函数原型说它接收到指向char的指针的指针,所以你应该使用它:

type
  PTR_Allocate = procedure(param1: ^^Char; param2: ^LongWord); cdecl;

一旦你确定它是正确的,那么就开始用更多类似Delphi的东西替换它们.如果你跳过这第一步,你可能永远无法做到正确,因为你只会继续改变错误的东西.

所以,你确定以上是对的吗?不完全的. Delphi中的Char可能具有不同的含义,具体取决于产品版本.您正在使用Delphi 7,但您可能会升级,因此您可能会与其他人共享此代码,因此您应该明确您想要的Char大小.需要单字节类型时使用AnsiChar.

type
  PTR_Allocate = procedure(param1: ^^AnsiChar; param2: ^LongWord); cdecl;

现在我们可以开始让它看起来更像Delphi.一级指针参数可以用“var”或“out”指令替换.对每个参数执行此操作:

type
  PTR_Allocate = procedure(out param1: ^AnsiChar; var param2: LongWord); cdecl;

Pointer-to-AnsiChar是一种常见的类型,Delphi已经为它命名了:PAnsiChar.使用惯用名:

type
  PTR_Allocate = procedure(out param1: PAnsiChar; var param2: LongWord); cdecl;

最后,你可能希望对整个概念采取一些自由,即完全涉及角色.你明确地为任意字节缓冲区分配内存,所以Byte可能是比任何字符类型更好的选择.最近的Delphi版本声明了一个指向字节的指针类型,所以使用:

type
  PTR_Allocate = procedure(out param1: PByte; var param2: LongWord); cdecl;

现在开始使用SetAllocateFunction.它表示它接收一个PTR_Allocate参数,该参数是一个指向函数的指针. Delphi的过程类型是隐式指针,因此我们上面声明的类型已经完全适合Delphi等价.不要通过引用传递额外的“var”指令,否则即使在程序尝试分配任何内存之前,您也会遇到问题.这是其他答案忽略的问题.

procedure SetAllocateFunction(param: PTR_Allocate); cdecl;

不要在名称的开头添加下划线,除非您想要调用自己的代码不方便.如果它是使用不同的名称从DLL导出的,那么在编写函数的实现时使用“name”子句:

procedure SetAllocateFunction; extern 'foo.dll' name '_SetAllocateFunction';

最后,如何实现分配功能.从匹配PTR_Allocate签名的内容开始,然后继续使用原始C代码中的尽可能翻译实现它.

procedure Allocate(out pbuffer: PByte; var psize: LongWord; cdecl;
begin
  psize := psize * 2;
  GetMem(pbuffer,psize);
end;

您可以使用之前的功能进行设置:

SetAllocateFunction(Allocate);

注意我不需要单独的变量,我没有使用@运算符.如果你需要使用@运算符来提及函数指针,在大多数情况下,你做错了.你通常不需要它.使用该运算符可以隐藏程序中的错误,例如签名不匹配,因为默认设置是@运算符无类型.使用它从函数指针中删除类型,并且无类型指针与Delphi中的所有内容兼容,因此它们适用于任何其他函数指针类型,包括具有错误签名的类型.

当编译器已经指示它已经尝试调用该函数时,仅在函数指针上使用@,例如通过提及您没有足够的参数或提及函数的返回类型.

.net 调用delphi 的DLL

.net 调用delphi 的DLL

总结

以上是小编为你收集整理的.net 调用delphi 的DLL全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

C# 调用 Delphi DLL

C# 调用 Delphi DLL

l

技术实现 
    
  如何逐步实现动态库的加载,类型的匹配,动态链接库函数导出的定义,参考下面宏定义即可: 
 #define LIBEXPORT_API extern "C" __declspec(dllexport) 
  
  第一步,我先从简单的调用出发,定义了一个简单的函数,该函数仅仅实现一个整数加法求和: 
   
  LIBEXPORT_API int mySum(int a,int b){ return a+b;} 
  C# 导入定义: 
   
  public class RefComm 
  { 
  [DllImport("LibEncrypt.dll", 
      EntryPoint=" mySum ", 
      CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] 
      public static extern int mySum (int a,int b); 
  } 
  在C#中调用测试: 
   
  int iSum = RefComm.mySum(,); 
  
  运行查看结果iSum为5,调用正确。第一步试验完成,说明在C#中能够调用自定义的动态链接库函数。 
   
  第二步,我定义了字符串操作的函数(简单起见,还是采用前面的函数名),返回结果为字符串: 
   
  LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a); return a;} 
  C# 导入定义: 
   
  public class RefComm 
  { 
  [DllImport("LibEncrypt.dll", 
       EntryPoint=" mySum ", 
       CharSet=CharSet.Auto, 
       CallingConvention=CallingConvention.StdCall)] 
       public static extern string mySum (string a, string b); 
  } 
  在C#中调用测试: 
   
  string strDest=""; 
  string strTmp= RefComm.mySum("45", strDest); 

  运行查看结果 strTmp 为"45",但是strDest为空。我修改动态链接库实现,返回结果为串b: 
   
  LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a) return b;} 
  修改 C# 导入定义,将串b修改为ref方式: 
   
  public class RefComm 
  { 
  [DllImport("LibEncrypt.dll", 
       EntryPoint=" mySum ", 
       CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)] 
       public static extern string mySum (string a, ref string b); 
  } 
  在C#中再调用测试: 
   
  string strDest=""; 
  string strTmp= RefComm.mySum("45", ref strDest); 
    运行查看结果 strTmp 和 strDest 均不对,含不可见字符。再修改 C# 导入定义,将CharSet从Auto修改为Ansi: 
   
  public class RefComm 
  { 
  [DllImport("LibEncrypt.dll", 
       EntryPoint=" mySum ", 
       CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] 
       public static extern string mySum (string a, string b); 
  } 
  在C#中再调用测试: 
   
  string strDest=""; 
  string strTmp= RefComm. mySum("45", ref strDest); 
    运行查看结果 strTmp 为"45",但是串 strDest 没有赋值。第二步实现函数返回串,但是在函数出口参数中没能进行输出。再次修改 C# 导入定义,将串b修改为引用(ref): 
   
  public class RefComm 
  { 
  [DllImport("LibEncrypt.dll", 
       EntryPoint=" mySum ", 
       CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] 
       public static extern string mySum (string a, ref string b); 
  } 
  
  运行时调用失败,不能继续执行。 
   
  第三步,修改动态链接库实现,将b修改为双重指针: 
   
  LIBEXPORT_API char *mySum(char *a,char **b){sprintf((*b),"%s",a); return *b;} 
  C#导入定义: 
   
  public class RefComm 
  { 
  [DllImport("LibEncrypt.dll", 
       EntryPoint=" mySum ", 
       CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] 
       public static extern string mySum (string a, ref string b); 
  } 
  在C#中调用测试: 
   
  string strDest=""; 
  string strTmp= RefComm. mySum("45", ref strDest); 
    
  运行查看结果 strTmp 和 strDest 均为"45",调用正确。第三步实现了函数出口参数正确输出结果。 
   
  第四步,修改动态链接库实现,实现整数参数的输出: 
   
  LIBEXPORT_API int mySum(int a,int b,int *c){ *c=a+b; return *c;} 
  C#导入的定义: 
   
  public class RefComm 
  { 
  [DllImport("LibEncrypt.dll", 
       EntryPoint=" mySum ", 
       CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)] 
       public static extern int mySum (int a, int b,ref int c); 
  } 
  在C#中调用测试: 
   
  int c=0; 
  int iSum= RefComm. mySum(,, ref c); 
  
  运行查看结果iSum 和c均为5,调用正确。 
    
  经过以上几个步骤的试验,基本掌握了如何定义动态库函数以及如何在 C# 定义导入,有此基础,很快我实现了变长加密函数在 C# 中的调用,至此目标实现。 
   
  三、结论 
    
  在 C# 中调用 C++ 编写的动态链接库函数,如果需要出口参数输出,则需要使用指针,对于字符串,则需要使用双重指针,对于 C# 的导入定义,则需要使用引用(ref)定义。 
    
  对于函数返回值,C# 导入定义和 C++ 动态库函数声明定义需要保持一致,否则会出现函数调用失败。定义导入时,一定注意 CharSet 和 CallingConvention 参数,否则导致调用失败或结果异常。运行时,动态链接库放在 C# 程序的目录下即可,我这里是一个 C# 的动态链接库,两个动态链接库就在同一个目录下运行。 

C# 调用delphi编写的dll

C# 调用delphi编写的dll

技术实现

如何逐步实现动态库的加载,类型的匹配,动态链接库函数导出的定义,参考下面宏定义即可:
#define LIBEXPORT_API extern "C" __declspec(dllexport)

第一步,我先从简单的调用出发,定义了一个简单的函数,该函数仅仅实现一个整数加法求和:

LIBEXPORT_API int mySum(int a,int b){ return a+b;}
C# 导入定义:

public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern int mySum (int a,int b);
}
在C#中调用测试:

int iSum = RefComm.mySum(,);

运行查看结果iSum为5,调用正确。第一步试验完成,说明在C#中能够调用自定义的动态链接库函数。

第二步,我定义了字符串操作的函数(简单起见,还是采用前面的函数名),返回结果为字符串:

LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a); return a;}
C# 导入定义:

public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, string b);
}
在C#中调用测试:

string strDest="";
string strTmp= RefComm.mySum("45", strDest);

运行查看结果 strTmp 为"45",但是strDest为空。我修改动态链接库实现,返回结果为串b:

LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a) return b;}
修改 C# 导入定义,将串b修改为ref方式:

public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}
在C#中再调用测试:

string strDest="";
string strTmp= RefComm.mySum("45", ref strDest);
运行查看结果 strTmp 和 strDest 均不对,含不可见字符。再修改 C# 导入定义,将CharSet从Auto修改为Ansi:

public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, string b);
}
在C#中再调用测试:

string strDest="";
string strTmp= RefComm. mySum("45", ref strDest);
运行查看结果 strTmp 为"45",但是串 strDest 没有赋值。第二步实现函数返回串,但是在函数出口参数中没能进行输出。再次修改 C# 导入定义,将串b修改为引用(ref):

public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}

运行时调用失败,不能继续执行。

第三步,修改动态链接库实现,将b修改为双重指针:

LIBEXPORT_API char *mySum(char *a,char **b){sprintf((*b),"%s",a); return *b;}
C#导入定义:

public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}
在C#中调用测试:

string strDest="";
string strTmp= RefComm. mySum("45", ref strDest);

运行查看结果 strTmp 和 strDest 均为"45",调用正确。第三步实现了函数出口参数正确输出结果。

第四步,修改动态链接库实现,实现整数参数的输出:

LIBEXPORT_API int mySum(int a,int b,int *c){ *c=a+b; return *c;}
C#导入的定义:

public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern int mySum (int a, int b,ref int c);
}
在C#中调用测试:

int c=0;
int iSum= RefComm. mySum(,, ref c);

运行查看结果iSum 和c均为5,调用正确。

经过以上几个步骤的试验,基本掌握了如何定义动态库函数以及如何在 C# 定义导入,有此基础,很快我实现了变长加密函数在 C# 中的调用,至此目标实现。

三、结论

在 C# 中调用 C++ 编写的动态链接库函数,如果需要出口参数输出,则需要使用指针,对于字符串,则需要使用双重指针,对于 C# 的导入定义,则需要使用引用(ref)定义。

对于函数返回值,C# 导入定义和 C++ 动态库函数声明定义需要保持一致,否则会出现函数调用失败。定义导入时,一定注意 CharSet 和 CallingConvention 参数,否则导致调用失败或结果异常。运行时,动态链接库放在 C# 程序的目录下即可,我这里是一个 C# 的动态链接库,两个动态链接库就在同一个目录下运行。

我们今天的关于vb.net 调用Delphi dll问题vb调用dll实例的分享就到这里,谢谢您的阅读,如果想了解更多关于(Delphi)使用函数指针参数调用DLL、.net 调用delphi 的DLL、C# 调用 Delphi DLL、C# 调用delphi编写的dll的相关信息,可以在本站进行搜索。

本文标签: