从C#调用DLL德尔福产生意想不到的结果 [英] Calling a Delphi DLL from C# produces unexpected results

查看:140
本文介绍了从C#调用DLL德尔福产生意想不到的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有没有写,但需要从C#ASP.NET 3.5应用程序调用DLL德尔福。下面是函数的定义,我从开发商得到了:

I have a Delphi DLL that I did not write, but need to call from a C# ASP.NET 3.5 app. Here is the function definition I got from the developers:

function CreateCode(SerialID : String; 
    StartDateOfYear, YearOfStartDate, YearOfEndDate, DatePeriod : Word; 
    CodeType,RecordNumber,StartHour,EndHour : Byte) : PChar;
    external 'CreateCodeDLL.dll';

和这里是我的C#代码:

And here is my C# code:

[DllImport( "CreateCodeDLL.dll", 
    CallingConvention = CallingConvention.StdCall, 
    CharSet=CharSet.Ansi)]
public static extern IntPtr CreateCode( string SerialID,
                                        UInt16 StartDateOfYear,
                                        UInt16 YearOfStartDate,
                                        UInt16 YearOfEndDate,
                                        UInt16 DatePeriod,
                                        Byte CodeType,
                                        Byte RecordNumber,
                                        Byte StartHour,
                                        Byte EndHour);



最后,我调用此方法:

And finally, my call to this method:

//The Inputs 
String serialID = "92F00000B4FBE";
UInt16 StartDateOfYear = 20;
UInt16 YearOfStartDate = 2009;
UInt16 YearOfEndDate = 2009;
UInt16 DatePeriod = 7;
Byte CodeType = 1;
Byte RecordNumber = 0;
Byte StartHour = 15;
Byte EndHour = 14;            

// The DLL call
IntPtr codePtr = CodeGenerator.CreateCode(serialID, StartDateOfYear, 
                YearOfStartDate, YearOfEndDate, DatePeriod, CodeType, 
                RecordNumber, StartHour, EndHour);

// Take the pointer and extract the code in a string
String code = Marshal.PtrToStringAnsi(codePtr);



我每次重新编译这个确切的代码并运行它,它会返回一个不同的值。预期值是由号码10位数代码。返回的值实际上是12位。

Every time I re-compile this exact code and run it, it returns a different value. The expected value is a 10-digit code comprised of numbers. The returned value is actually 12 digits.

信息的最后一个重要部分是,我有一个具有图形用户界面,让我来测试DLL测试.EXE。使用.EXE每个测试返回相同的10位数字(预期结果)。

The last important piece of information is that I have a test .EXE that has a GUI that allows me to test the DLL. Every test using the .EXE returns the same 10-digit number (the expected result).

所以,我相信,我宣布我的调用DLL不正确。思考?

So, I have to believe that I have declared my call to the DLL incorrectly. Thoughts?

推荐答案

Delphi使用所谓的 FASTCALL 调用约定由默认。这意味着,编译器试图将参数传递给在CPU寄存器的函数和仅使用堆栈,如果有比自由寄存器多个参数。你实际上使用例如Delphi使用(EAX,EDX,ECX)的前三个参数的函数。

在C#代码的 STDCALL 调用约定,它指示编译器通过栈来传递参数(以相反的顺序,也就是说最后的参数被推向第一),并让被叫方清理堆栈。

相反,< STRONG>的 CDECL 的调用使用C / C ++编译器强制调用者清除栈。

只要确保你使用的都是相同的调用约定两侧。 STDCALL大多使用,因为它几乎可以随处使用,并且在每一个编译器支持(Win32 API的也使用这种约定)。

注意 FASTCALL 不被.NET支持反正

Delphi uses the so called fastcall calling convention by default. This means that the compiler tries to pass parameters to a function in the CPU registers and only uses the stack if there are more parameters than free registers. For example Delphi uses (EAX, EDX, ECX) for the first three parameters to a function.
In your C# code you're actually using the stdcall calling convention, which instructs the compiler to pass parameters via the stack (in reverse order, i.e. last param is pushed first) and to let the callee cleanup the stack.
In contrast, the cdecl calling used by C/C++ compilers forces the caller to cleanup the stack.
Just make sure you're using the same calling convention on both sides. Stdcall is mostly used because it can be used nearly everywhere and is supported by every compiler (Win32 APIs also use this convention).
Note that fastcall isn't supported by .NET anyway.

这篇关于从C#调用DLL德尔福产生意想不到的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆