在c#中的一个dll中调用Delphi方法 [英] Calling a Delphi method in a dll from c#

查看:195
本文介绍了在c#中的一个dll中调用Delphi方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 函数SMap4Ovr(const OverFileName:ShortString ; 
const Aclay:Integer;
const Acarbon:Double;
out errstr:ShortString):WordBool;

我在C#中使用以下导入:

  [DllImport(SMap.dll,CallingConvention = CallingConvention.StdCall,CharSet = CharSet.Ansi)] 
public static extern bool SMap4Ovr(
string OverFileName ,
int Aclay,
double Acarbon,
out string errstr
);

但是我收到了AccessViolationException。



我似乎可以调用一些简单的方法,在DLL中有字符串参数,但不是int或双精度。



我也尝试过CallingConvention = CallingConvention.Cdecl,但这给我一样的错误。

解决方案

当编写互操作代码时,界面的双方都是匹配的各方面。以下是双方同意的主要问题:


  1. 呼叫约定

  2. 参数列表。

  3. 参数类型和语义。

第一个观察结果是您的呼叫约定不匹配。您在C#端有Delphi端的注册 stdcall 。 Delphi 注册约定对Delphi是私有的,所以你应该使用 stdcall



其次,您的字符串参数类型不匹配。 Delphi shortstring 是一种数据类型,当Delphi 2被发布时成为遗产,应该被视为上个世纪的遗物。它从来不是一个有效的interop类型,在p / invoke框架中没有什么可以用来匹配它。虽然您可以尝试手动编组,但是当有简单的解决方案可用时,这是很多工作,根本不需要。你应该尝试忘记所有关于 shortstring



您需要使用接口两端可以使用的字符串类型。您可以使用null终止的C字符串,但是更好和更简单的选择是Delphi中的COM BSTR ,它是 WideString



所以最后的结果如下。



Delphi p>

 函数SMap4Ovr(
OverFileName:WideString;
Aclay:Integer;
Acarbon:Double;
out errstr:WideString
):WordBool;标准

C#

  [DllImport(SMap.dll)] 
public static extern bool SMap4Ovr(
[MarshalAs(UnmanagedType.BStr)]
string OverFileName,
int Aclay,
double Acarbon,
[MarshalAs(UnmanagedType.BStr)]
out string errstr
);

我没有打扰在 DllImport ,因为默认值为 stdcall



使用 WideString 时,请注意您不尝试将其用作返回值。因为Delphi对返回值使用非标准语义,所以只能使用适合寄存器的简单类型作为返回值。


I am trying to call a method in a Delphi DLL with the following signature:

 function SMap4Ovr(const OverFileName       : ShortString    ;
                    const Aclay              : Integer        ;
                    const Acarbon            : Double         ;
                    out   errstr             : ShortString): WordBool;

I am using the following import in C#:

        [DllImport("SMap.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    public static extern bool SMap4Ovr(
        string OverFileName,
        int Aclay,
        double Acarbon,
        out string errstr
        );

But I am getting a AccessViolationException.

I seem to be able to call into a couple of simpler methods in the DLL that have string parameters but not ints or doubles.

I have also tried with the CallingConvention = CallingConvention.Cdecl but this gives me the same error.

解决方案

When writing interop code it is critical that both sides of the interface match in every way. Here are the main issues that you must make agree on both sides:

  1. Calling conventions.
  2. Parameters lists.
  3. Parameter types and semantics.

The first observation is that your calling conventions do not match. You have register on the Delphi side and stdcall on the C# side. The Delphi register convention is private to Delphi and so you should use stdcall.

Secondly, your string parameter types do not match. The Delphi shortstring is a data type that became legacy when Delphi 2 was released and should be considered a relic from the previous century. It was never a valid interop type, and there's nothing in the p/invoke framework that can be used to match it. Whilst you could attempt to do the marshalling by hand, this is a lot of work that is simply not needed when there are simple solutions available. You should try to forget all about shortstring.

You need to use a string type that both sides of the interface can work with. You could use null-terminated C strings, but a better and simpler choice is the COM BSTR which is WideString in Delphi.

So, the final result is as follows.

Delphi

function SMap4Ovr(
    OverFileName: WideString;
    Aclay: Integer;
    Acarbon: Double;
    out errstr: WideString
): WordBool; stdcall;

C#

[DllImport("SMap.dll")]
public static extern bool SMap4Ovr(
    [MarshalAs(UnmanagedType.BStr)] 
    string OverFileName,
    int Aclay,
    double Acarbon,
    [MarshalAs(UnmanagedType.BStr)] 
    out string errstr
);

I did not bother specifying the calling convention on the DllImport since the default is stdcall. If you prefer you can be explicit about this.

Be careful when using WideString that you don't attempt to use it as a return value. Because Delphi uses non-standard semantics for return values, you can only use simple types that fit into a register as return values.

这篇关于在c#中的一个dll中调用Delphi方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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