2

I'm trying to compile This Example for unmanaged export in XE but I getting (PE9) Unknown identifier "UnmanagedExport" error when build.

  1. Under Compatibility select "Allow unsafe code"
  2. Under Build, find the General Section and change CPU Type to "x86"
  3. Right Click on the "ClassLibraryX" tab that was created and select "Save selected Items"
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

Any idea?

@David:Thanks for answer. I've tried your tip

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;

but same error is continues.

@David 2 :):

I've changed code in this way:

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.

Same error :)

@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.

still same error. :,( Can you try on your prism ide my sample project for me please? Thanks for answers.

    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

my oxygene version 4.0.25.791 I suppose.

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

@David: I tried compile on command line too. here is results

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>

probably your right. maybe something wrong with my compiler. But i didnt see any error during install Delphi prism.

@Rudy: I was tried VS2010 ide before this. As I Said. Maybe i reinstall delphi prism or try different machine. I'll write results if solve.

Community
  • 1
  • 1
  • You still need System.Runtime.InteropServices to get the CallingConvention enumeration. I'd guess that you actually have a different error now. Now the error will be `Unknown identifier "CallingConvention"` – David Heffernan Sep 26 '11 at 09:27
  • What version of Oxygene do you have? – David Heffernan Sep 26 '11 at 10:54
  • I dont know. I just installed delphi prism xe (powered ny oxygene). How can i learn version. –  Sep 26 '11 at 11:24
  • I've no idea. I never used Prism. Are you sure you are getting `unknown identifier UnmanagedExport` error? That seems astounding to me given that you are using `RemObjects.Oxygene.System`. – David Heffernan Sep 26 '11 at 11:26
  • yeah!. Im sure. You can see in this picture http://img834.imageshack.us/img834/7451/error3f.png –  Sep 26 '11 at 11:33
  • Well, I can't see what's wrong. You seem to have followed all the instructions. For what it is worth, you can't export a managed string to unmanaged code, but that's a problem for you to solve later. – David Heffernan Sep 26 '11 at 11:40
  • I'm keeping try to solve problem.if i solve i'll share solution. Thanks anyway. –  Sep 26 '11 at 11:47
  • ISTM that RemObjects.Oxygene.System is included by default, since it also works if I don't include it explicitly. – Rudy Velthuis Sep 26 '11 at 21:06
  • @Rudy Yes that would appear to be so. It's the blind leading the blind here!! ;-) – David Heffernan Sep 27 '11 at 08:20
  • @David: Not entirely blind. I have done a few small things in Oxygene before. And in the land of the blind... – Rudy Velthuis Sep 27 '11 at 08:35
  • @Rudy You at least have the product!! ;-) – David Heffernan Sep 27 '11 at 08:42
  • I'm just installed Delphi Prism XE2. But result was the same.[Error S.Shoot](http://i.stack.imgur.com/QhgL1.png) Anyway. I give up. –  Sep 27 '11 at 13:32

3 Answers3

1

I think the main problem is that you need to use the RemObjects.Oxygene.System namespace which is where UnmanagedExport is defined.

In fact it looks like that uses is not needed (see below).


You also need to make the method a class method.

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

And likewise in the implementation.

Note that function and procedure are deprecated in Prism and you should use method instead.

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

This information was gleaned from the docwiki.


I downloaded the command line compiler for Prism XE. This is version 4.0 and so supports the UnmanagedExport attribute.

I successfully compiled the following unit:

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.

The output was:

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.

This produced a DLL which I verified contained a single exported function named foo.

Next I called the DLL from Python via ctypes:

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

Thus I can only conclude that your problem is not with the code. You perhaps have a mis-configured Prism installation. Could you try to repeat my command line above? Could you perform a re-installation of Prism.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks but nothing changed. I'v attached my project link under my question. –  Sep 26 '11 at 09:17
  • Project created in delphi prism xe and .net 4.0 project. –  Sep 26 '11 at 09:18
  • Nothing changed because you didn't make the change! I'll try again. You must add `uses RemObjects.Oxygene.System`. That's where `UnmanagedExport` is defined. Please read the first sentence of my (updated) answer. – David Heffernan Sep 26 '11 at 09:19
  • No just i went lunch. :) I'm going to try now. –  Sep 26 '11 at 10:42
  • I updated my answer. I can make your code work fine. So can Rudy. I think the problem is the configuration of your system. – David Heffernan Sep 26 '11 at 12:28
  • "RemObjects.Oxygene.System" is included by default, you should not need to have it in the uses clause. – marc hoffman Sep 29 '11 at 16:16
  • @marc Thanks. I kind of worked that out. Just like System.pas in native Delphi I guess. It seems clear that Fatih's problem is to do with the installation of Prism or .net, but I just don't know enough to solve the problem. You might be better placed to do so. ;-) – David Heffernan Sep 29 '11 at 16:19
0

I Solved problem this way. 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;
      }



   }
}

And pascal side

_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;    
  • Fun fact: I first released this on the former oxygene newsgroup for Oxygene, not C#, (because D.Net had something similar) However, I only test and target it for C# now. Because Oxygene can do that just fine on its own since shortly afterward. You should file a bug at codecentral to get this sorted out, IMO. – Robert Giesecke May 07 '12 at 13:28
0

This works for me, using Prism XE2 (5.0.29.893) in the VS2010 Shell. This probably won't work in a version earlier than 3.0.19:

  • Start a new project - Class Library
  • Rename to XClassLibrary and save
  • set options as you did (allow unsafe code, x86 target)

Make the code of Class1 look like this:

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.

Then Build > Build Solution. I get a successful build:

------ 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 ==========
Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • my oxygene version 4.0.25.791 I suppose. Added command line result in main question. –  Sep 26 '11 at 12:18
  • can you compress and upload your project please. Maybe i miss something. –  Sep 26 '11 at 12:20
  • I didn't use the command line, I used the VS 2010 Shell. Could it be that your command line configuration misses some parts? – Rudy Velthuis Sep 26 '11 at 12:28
  • @Rudy I just installed the command line Prism XE. It works fine too. Fatih is using VS in any case - this can be seen from the screenshot in the question. Since you and I can both make this work there must be something messed up in the Prism installation on Fatih's machine. – David Heffernan Sep 26 '11 at 12:35