为什么更正可选参数会导致访问冲突?

时间:2016-03-29 07:01:30

标签: c# delphi

在c#中与Delphi DLL交谈。 Delphi函数的定义是

function oziCreateWP(var Name: pchar; Symbol: integer; lat, lon: double; Altitude: double; 
  wpDate: double; MapDisplayFormat: integer; PointerDirection: integer;
  GarminDisplayFormat: integer; ForeColor, BackColor: integer;
  ProximityDistance: integer; var Description: pchar; FontSize: integer;
  FontStyle: integer; SymbolSize: integer): integer; stdcall;

该函数使用指定的参数在指定位置创建一个航点。返回值是Waypoint创建的内部OziExplorer编号。如果稍后要在程序中操作Waypoint,则可能需要在本地存储此数字。对于大多数参数,可以指定值-1,这意味着使用OziExplorer默认值。 **表示上述选项适用于该字段。

Name - the name of the waypoint Symbol - the symbol number; ** lat,lon - the position in decimal degrees (WGS 84 datum) Altitude - in meters (-777 = altitude unknown) wpDate - the format of the date is at the end of this document; -1 = use todays date and time. MapDisplayFormat - 0 to 8; ** PointerDirection - 0 to 3; ** GarminDisplayFormat - 0 to 2; ** ForeColor - RGB color; ** BackColor - RGB color; ** ProximityDistance - in meters (0 = no proximity) Description - text string FontSize - in points; ** FontStyle - 0 = normal; 1 = bold; ** SymbolSize - 17 = normal; **

我的C#定义是..

[DllImport("oziapi.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int oziCreateWP(ref string Name, int Symbol, double lat, double lon,
    double Altitude = oziAltitudeNull, double wpDate = oziDefault,
    int MapDisplayFormat = oziDefault, int PointerDirection = oziDefault,
    int GarminDisplayFormat = oziDefault, int ForeColor = oziDefault,
    int BackColor = oziDefault, int ProximityDistance = oziDefault, 
    ref string Description, int FontSize = oziDefault, 
    int FontStyle = oziDefault, int SymbolSize = oziDefault);

我的实施代码是..

private void btnCreateAManualWP_Click(object sender, EventArgs e)
{
    int nTemp;
    int nAlt = -777;
    int nNegOne = -1;
    int nZero = 0;
    string cName = cWPName.Text;
    string cDescription = "No Description";
    nTemp = oziCreateWP(ref cName, nNegOne, Convert.ToDouble(cWPLat.Text), 
        Convert.ToDouble(cWPLon.Text), nAlt, nNegOne, nNegOne, nNegOne, nNegOne, nNegOne,
        nNegOne, nZero, ref cDescription, nNegOne, nNegOne, nNegOne);
    nTemp = oziRefreshMap();
}

有了这个,我收到一个标记描述的CS1737 Optional parameters must appear after all required parameters错误消息。 如果我更正了定义中的参数顺序和修复此问题的调用,我在运行时会收到内存访问冲突错误。

1 个答案:

答案 0 :(得分:2)

参数的顺序是二进制接口的一部分。参数顺序必须在接口的两侧相同。如果更改C#代码中的顺序,则需要更改Delphi代码以匹配。

据推测,Delphi代码无法更改。因此,您需要在不更改参数顺序的情况下修复C#代码。通过删除参数默认值的设置来做到这一点。

ref string参数几乎肯定是错误的,尽管如果没有更多细节,不可能100%确定它们应该是什么。该库的文档可能会解释如何处理var PChar参数。

如果SetLastError = true是正确的,我会感到惊讶。这个库真的叫SetLastError吗?