为什么UnManaged Export示例在prism XE中不起作用

时间:2011-09-26 08:12:00

标签: visual-studio delphi unmanaged

我正在尝试为XE中的非托管导出编译This Example但是在构建时我得到(PE9)未知标识符“UnmanagedExport”错误。

  1. 在兼容性下选择“允许不安全代码”
  2. 在Build下,找到General Section并将CPU Type更改为“x86”
  3. 右键单击已创建的“ClassLibraryX”选项卡,然后选择“保存所选项目”
  4. namespace exptest;
    
    interface
        uses
          System.Runtime.InteropServices;
    
    type
      clstest = public static class
      private
      protected
      public
    
         [UnmanagedExport('xmsg',CallingConvention.StdCall)]
          function xmsg(amsg : String):String;
      end;
    
    implementation
    
        function clstest.xmsg(amsg: String):String;
        Begin
            Result := amsg + ' mesajı için geri dönüş';
        end;
    
    
    
    end.
    

    Error Window

    有什么想法吗?

    @David:谢谢你的回答。我已经尝试了你的提示

    public
    
         [UnmanagedExport('xmsg',CallingConvention.StdCall)]
          class method xmsg(amsg : String):String;
      end;
    
    implementation
    
        class method clstest.xmsg(amsg: String):String;
        Begin
            Result := amsg + ' mesajı için geri dönüş';
        end;
    

    但同样的错误仍在继续。

    @David 2 :):

    我已经用这种方式更改了代码:

    namespace exptest;
    
    interface
        uses
          RemObjects.Oxygene.System;
    
    type
      clstest = public class
      private
      protected
      public
    
         [UnmanagedExport('xmsg',CallingConvention.StdCall)]
          class method xmsg(amsg : String):String;
      end;
    
    implementation
    
        class method clstest.xmsg(amsg: String):String;
        Begin
            Result := amsg + ' mesajı için geri dönüş';
        end;
    
    
    
    end.
    

    同样的错误:)

    @david 3

    namespace exptest;
    
    interface
        uses
          RemObjects.Oxygene.System,System.Runtime.InteropServices;
    
    
    type
      clstest = public class
      private
      protected
      public
    
         [UnmanagedExport('xmsg',CallingConvention.StdCall)]
          class method xmsg(amsg : String):String;
      end;
    
    implementation
    
        class method clstest.xmsg(amsg: String):String;
        Begin
            Result := 'a return value for '+amsg ;
        end;
    
    
    
    end.
    

    仍然是同样的错误。 :( 你可以帮我试试你的棱镜my sample project吗?谢谢你的回答。

        C:\Program Files\Embarcadero\Delphi Prism\bin>oxygene -version
    RemObjects Oxygene for .NET - Version 4.0.25.791
    Copyright RemObjects Software 2003-2009. All rights reserved.
    Exclusively licensed for Delphi Prism.
    
      Configuration Release not found
    

    我的氧气版本4.0.25.791我想。

    ..............................

    @David:我也尝试在命令行上编译。这是结果

    C:\Documents and Settings\XPMUser\Desktop\exptest\exptest>oxygene /allowunsafe:y
    es /type:library /cputype:x86 clstest.pas
    RemObjects Oxygene for .NET - Version 4.0.25.791
    Copyright RemObjects Software 2003-2009. All rights reserved.
    Exclusively licensed for Delphi Prism.
    
      Preparing resources...
      Compiling...
      C:\Documents and Settings\XPMUser\Desktop\exptest\exptest\clstest.pas(14,22) :
     Error : (PE9) Unknown identifier "UnmanagedExport"
    
      Exiting with 1.
    
    C:\Documents and Settings\XPMUser\Desktop\exptest\exptest>
    

    可能是你的权利。也许我的编译器有问题。但是我在安装Delphi prism时没有看到任何错误。

    @Rudy:在此之前我曾尝试过VS2010 ide。就像我说的。也许我重新安装delphi棱镜或尝试不同的机器。如果解决,我会写结果。

3 个答案:

答案 0 :(得分:1)

我认为主要的问题是你需要使用RemObjects.Oxygene.System命名空间,这是UnmanagedExport的定义。

实际上看起来不需要uses(见下文)。


您还需要将该方法设为类方法。

[UnmanagedExport('xmsg',CallingConvention.StdCall)]
class function xmsg(amsg: String): String;

同样在实施中。

请注意,functionprocedure在Prism中已弃用,您应该使用method代替。

[UnmanagedExport('xmsg',CallingConvention.StdCall)]
class method xmsg(amsg: String): String;

此信息来自docwiki


我下载了Prism XE的命令行编译器。这是版本4.0,因此支持UnmanagedExport属性。

我成功编译了以下单元:

namespace ExportTest;

interface

uses
  System.Runtime.InteropServices;

type
  test = class
    [UnmanagedExport('foo', CallingConvention.StdCall)]
    class method foo: Integer;
  end;

implementation

class method test.foo: Integer;
begin
  Result := 666;
end;

end.

输出结果为:

C:\Desktop>oxygene /allowunsafe:yes /type:library /cputype:x86 test.pas
RemObjects Oxygene for .NET - Version 4.0.25.791
Copyright RemObjects Software 2003-2009. All rights reserved.
Exclusively licensed for Delphi Prism.

  Preparing resources...
  Compiling...
  Compile complete.

这产生了一个我验证的DLL包含一个名为foo的导出函数。

接下来,我通过ctypes从Python调用DLL:

>>> import ctypes
>>> lib = ctypes.WinDLL('test.dll')
>>> lib.foo()
666

因此,我只能得出结论,你的问题不在于代码。您可能安装了错误配置的Prism。你能尝试重复我上面的命令行吗?你能不能重新安装Prism。

答案 1 :(得分:0)

这适用于我,在VS2010 Shell中使用Prism XE2(5.0.29.893)。 这可能不适用于3.0.19之前的版本

  • 开始一个新项目 - 类库
  • 重命名为XClassLibrary并保存
  • 像你一样设置选项(允许不安全的代码,x86目标)

使Class1的代码如下所示:

namespace XClassLibrary;

interface

uses
  System.Runtime.InteropServices; 

type
  Class1 = public class
  private
  protected
  public
    [UnmanagedExport('xmsg', CallingConvention.StdCall)]
    class method xmsg(aMsg: String): String;
  end;

implementation

class method Class1.xmsg(aMsg: string): string;
begin
  Result := aMsg + ' plus some Turkish text';
end;

end.

然后构建>构建解决方案我得到了一个成功的构建:

------ Build started: Project: XClassLibrary, Configuration: Debug ------
    XClassLibrary -> c:\users\administrator\documents\visual studio 2010\Projects\XClassLibrary\XClassLibrary\bin\Debug\XClassLibrary.dll
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

答案 2 :(得分:0)

我这样解决了问题。 RGiesecke.DllExport

using System;
using System.Collections.Generic;
using System.Text;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
using System.IO;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Configuration;


namespace thenamespace
{

   {

      private static some_members
      ...
      ...
      ...

      [DllExport(CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
      [return: MarshalAs(UnmanagedType.LPStr)]
      static String GetValue(
          [MarshalAs(UnmanagedType.LPStr)] String _url,
          [MarshalAs(UnmanagedType.LPStr)] String _username,
          [MarshalAs(UnmanagedType.LPStr)] String _password, 
          int _method,
          [MarshalAs(UnmanagedType.LPStr)] String _identid,
          int _isTestMode,
          int _TimeOutAsSecond,
          [MarshalAs(UnmanagedType.LPStr)] String _ProxyAddr,
          [MarshalAs(UnmanagedType.LPStr)] String _ProxyUsername,
          [MarshalAs(UnmanagedType.LPStr)] String _ProxyPassword)
      {
        ...
         return result;
      }



   }
}

帕斯卡方面

_fGetValue = function(_url, _username, _password: pAnsiChar; _method: Integer;
    _identid: pAnsiChar; _isTestMode : Integer; _TimeOutAsSecond:Integer;
    _ProxyAddr:PAnsiChar;_ProxyUsername:PAnsiChar;_ProxyPassword:PAnsiChar): pAnsiChar; stdcall;


...
...
...

var
  dllHandle: cardinal;
  dllFunc: _fGetValue;

  __url, __username, __password, __tckimlik, __result: pAnsiChar;
  __metod: Integer;__ProxyAddr:PAnsiChar;
  __ProxyUsername:PAnsiChar;__ProxyPassword:PAnsiChar;
begin
  Result := '';
  __result := '';

  dllHandle := LoadLibrary('thelib.dll');
  If dllHandle <> 0 then
  begin
    dllFunc := nil;
    @dllFunc := GetProcAddress(dllHandle, 'GetValue');

    if Assigned(dllFunc) then
      __result := dllFunc(__url, __username, __password, __metod, __identid,
      _isTestMode,_TimeOutAsSecond,__ProxyAddr,__ProxyUsername,__ProxyPassword)
    else
    Begin
      raise Exception.Create('Method is not found');
    End;
    Result := __result;
    FreeLibrary(dllHandle);
  end
else
begin
  raise Exception.Create('Library not found thelib.dll');
end;
end;