How to import C-files (.h/.c) in Oxygene?

Hello,

as mentioned above, would you be nice and tell me, how can i include a or some .h files ??

I really cant get around with this :confused:

Would be happy for any suggestions :slight_smile:

–Shpend

What are you trying to accomplish? Elements/Island supports using C header files for calling C based libraries, however it can’t compile C files.

Oh, yes,I ofc want just to include .h files not compiling c-code^^

I am playing around with some interessting performance-headers which someone published as open-source and I want to Benchmark them :slight_smile:

And for that, I want to know how can i include them.

https://docs.elementscompiler.com/Platforms/Cocoa/ImportingLibraries/

Is this also for Visual Studio?

Because it Looks just for Mac/Cocoa :confused:

I actually dont really know, how to use the header-importer’s Train-script?

How can I install the Train-script, I just found the git-hub-Project and downloaded it but I cant install it

Because, I cant build the Train-solution, when i press build it throws me 822 Syntax-Errors…

Hm, like what?

what do you mean exactly?

As I said, cant build because of 800 Errors :frowning:

ok, let me look into that OH WAIT, i can’t because i don’t know what they are!

Ok, do you want me to send you the Project or to declar which type o errors?

Well, there 800 Syntax error, dont know still what do you mean with “what they are”?

but here the Project:

train-master.zip (9.6 MB)

So there’s some confusion here. There’s no train based script yet for importing headers for Island, only for Toffee.

To currently use C based libraries there are two options:

  • Directly call header importer and create an fx/a pair that way
  • Use dllimport (only works for dll/so files)

Dll import is simple:

[DllImport('Kernel32.dll'), CallingConvention(CallingConvention.Stdcall)]
class method Beep(aFreq, aSeq: Integer);

Header Importer is trickier. The goal is to make a train script to make this easier but there isn’t one yet. The first step for HI is to create an import definition, this is a json file like:

{
  "TargetString": "i686-pc-windows-msvc",
  "Version": "3.18",
  "SDKVersionString": "3.18",
  "Imports": [
    {
      "Name": "sqlite3",
      "ForceNamespace": "sqlite3",
      "Files": [ "sqlite3.h" ],
      "IndirectFiles": [],
      "DepLibs": [ "sqlite3.lib" ],
      "ImportDefs": [
        { "Name": "_TryEnterCriticalSection@4", "Library": "Kernel32.dll" },
        { "Name": "_AreFileApisANSI@0", "Library": "Kernel32.dll" },
        { "Name": "_DeleteFileA@4", "Library": "Kernel32.dll" },
        { "Name": "_FormatMessageA@28", "Library": "Kernel32.dll" },
        { "Name": "_FormatMessageW@28", "Library": "Kernel32.dll" },
        { "Name": "_FreeLibrary@4", "Library": "Kernel32.dll" },
        { "Name": "_GetDiskFreeSpaceA@20", "Library": "Kernel32.dll" },
        { "Name": "_GetDiskFreeSpaceW@20", "Library": "Kernel32.dll" },
        { "Name": "_GetFileAttributesA@4", "Library": "Kernel32.dll" },
        { "Name": "_GetFileAttributesExW@12", "Library": "Kernel32.dll" },
        { "Name": "_GetFileSize@8", "Library": "Kernel32.dll" },
        { "Name": "_GetFullPathNameA@16", "Library": "Kernel32.dll" },
        { "Name": "_GetSystemTimeAsFileTime@4", "Library": "Kernel32.dll" },
        { "Name": "_GetTempPathA@8", "Library": "Kernel32.dll" },
        { "Name": "_GetTempPathW@8", "Library": "Kernel32.dll" },
        { "Name": "_HeapCreate@12", "Library": "Kernel32.dll" },
        { "Name": "_HeapDestroy@4", "Library": "Kernel32.dll" },
        { "Name": "_HeapReAlloc@16", "Library": "Kernel32.dll" },
        { "Name": "_HeapSize@12", "Library": "Kernel32.dll" },
        { "Name": "_HeapValidate@12", "Library": "Kernel32.dll" },
        { "Name": "_HeapCompact@8", "Library": "Kernel32.dll" },
        { "Name": "_LoadLibraryA@4", "Library": "Kernel32.dll" },
        { "Name": "_LoadLibraryW@4", "Library": "Kernel32.dll" },
        { "Name": "_LocalFree@4", "Library": "Kernel32.dll" },
        { "Name": "_LockFile@20", "Library": "Kernel32.dll" },
        { "Name": "_LockFileEx@24", "Library": "Kernel32.dll" },
        { "Name": "_QueryPerformanceCounter@4", "Library": "Kernel32.dll" },
        { "Name": "_SystemTimeToFileTime@8", "Library": "Kernel32.dll" },
        { "Name": "_UnlockFile@20", "Library": "Kernel32.dll" },
        { "Name": "_UnlockFileEx@20", "Library": "Kernel32.dll" },
        { "Name": "_WaitForSingleObjectEx@12", "Library": "Kernel32.dll" },
        { "Name": "_OutputDebugStringA@4", "Library": "Kernel32.dll" },
        { "Name": "_OutputDebugStringW@4", "Library": "Kernel32.dll" },
        { "Name": "_FlushViewOfFile@8", "Library": "Kernel32.dll" }
      ]
    }
  ],
  "Platform": "Windows"
}

There are a few important things here: Platform has to match the target platform (Windows in my case). TargetString has to match the targets target string (“TargetString”: “i686-pc-windows-msvc” for Windows 32bits).

Version is the file version (in a.b.c.d format) SDKVersionString is shown in the IDE (can be anything)

An import file can contain multiple imports, the same has just one, named “sqlite3”, ForceNamespace defines the namespace this is going to be defined in, “Files” contains the files to import from. Indirect files are the files that need to be imported, but shouldn’t be loaded directly, instead they are included indirectly by the files in “Files” via #include. Types defined in a file not mentioned in these two arrays are not imported, they are ignored. DepLibs contains the dependencies for the linker, ie the .o/.a/lib file.

The last bit here is the import defs. These are dll imports by this library that the compiler doesn’t know about, they define which symbol is defined in which dll, for example:
{ “Name”: “_TryEnterCriticalSection@4”, “Library”: “Kernel32.dll” },

TryEnterCriticalSection is defined in Kernel32.

Note: We don’t officially support custom imports via Header importer yet.

Thanks a lot carlo, but I also have then to mention something here^^

  1. I suggest you then, to take, at least for the current Moment, this line of the page out:
    Of course any other custom, third party or open source C APIs can be imported using HeaderImporter
    src: https://docs.elementscompiler.com/Platforms/Island/Windows/
    could be confusing otherwise :stuck_out_tongue:

  2. Am I able to just call 1 .h file in Oxygene via DllImport, even if it isnt a standardCall?

1: yes, it’s a work in progress. HI as it is isn’t very user friendly, hence what I Said.
2: You don’t call “h” files, you call dlls. That only works if you have a dll ofc, else you have to use header importer.

1 Like

Well, quite obviously i know how to pull the Train master branch, myself. It’s also safe too assume that it builds fine, for me, given that we’d not publish a project with 800 compile errors that we know about and call it good.

so i ask again: with what errors does it fail for you?

@ck @mh You meant I can directly include a C header file in Island project? Like, I can directly include Google TensorFlow C Api header file?

You cannot simply just add the C headerfile straight to the project, but you can create an Import Project, as described at Import Projects to generate a .fx file from the header, and you can then reference that .fx file (or the project, as project reference), like you would any other reference.

Let us know if you need any help creating the import. You can find some other imports, for reference, at GitHub - remobjects/recipes: Contains recipes for importing known open source projects — and once you have Tensorflow working, it might be cool to include that there.

This import works for me, if I coy the project into an folder Elements within the downloaded zip/tar.gz file:

Elements.zip (20.9 KB)

so the structure is like such:

in vNext (not today’s upcoming build), I’ve extended support for Import projects (and ay project really) to be a blessing to pull in the binaries remotely, so an import project can build w/o having to have all the binaries gathered in the right places manually. eg:

    <ImportLinkLibrary Include=".\lib\libtensorflow.dylib">
      <Remote>https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-darwin-x86_64-1.15.0.tar.gz</Remote>
      <Target>Island.macOS</Target>
    </ImportLinkLibrary>
    <ImportLinkLibrary Include=".\lib\tensorflow.dll">
      <Remote>https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-windows-x86_64-1.15.0.zip</Remote>
      <Target>Island.Windows</Target>
    </ImportLinkLibrary>
    <ImportLinkLibrary Include=".\lib\libtensorflow.so">
      <Remote>https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.15.0.tar.gz</Remote>
      <Target>Island.Linux</Target>
    </ImportLinkLibrary>

Thank you. But the generated TensorFlow.fx doesn’t seem to work. The architecture is x86_64, but TensorFlow.fx ended up in i386.

Also I created an Windows Island Console, added TensorFlow.fx (withOUT calling any tensor flow Apis, just reference it), it won’t compile.

Also, is there a converter to convert c header to oxygene .pas file?

Ah yes, the import project doesnt know the actual architecture of the .dll, so the project will “build” for i386 and x64, even though the former might not be supported. add an <Architecture>x86_64</Architecture> tag to the project, like such:

  <PropertyGroup Condition=" '$(Target)' == 'Island.Windows' ">
    <Mode>Island</Mode>
    <SubMode>Windows</SubMode>
    <Architecture>x86_64</Architecture>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Target)' == 'Island.Linux' ">
    <Mode>Island</Mode>
    <SubMode>Windows</SubMode>
    <Architecture>x86_64</Architecture>
  </PropertyGroup>