简体   繁体   中英

Create C/C++ library in Xcode and import it in C# .NETCore

I am trying to write an C/C++ dynamic library in Xcode, compile it to an .dylib library package (or whatever you call that) and [DLLImport] it in .NET Core.

Little background on why: A Chinese company develops a device for us, for integrating their device in our software they wrote a demo library in Borland C++ to test the integration and that worked out.

Now I want to know if it is possible for us to import an C++ library, written in Xcode, into our application as well, using .NET Core or Xamarin.

Now I am a rooky at C/C++ and I am a bit new to the cross platform solutions provided by Microsoft. But according to this github question DLLImport should work on Mac. Now I am wondering how.

So, in my best effort to write a C++ library:

ApiFunc.h

#ifndef ApiFuncH
#define ApiFuncH

double mean(double x, double y);

typedef void (*SignalHandler)(int signum);
typedef int (*OPEN_IMAGE_FILE)(char*);

extern OPEN_IMAGE_FILE open(char *FileName);
extern  SignalHandler signal(int signum, SignalHandler handler);

class TAPIFunc
{
public:
    int OpenImageFile(char *FileName);
};
#endif

ApiFunc.cpp

#pragma hdrstop

#include "ApiFunc.h"

double mean(double x, double y){
    return x * y;
}

int TAPIFunc::OpenImageFile(char *FileName)
{
    return 5;
}

Just trying some different methods out there... So this compiles to a libtestmachw.dylib

I import that into my .NET Core console application:

    [DllImport("libtestmachw.dylib", EntryPoint = "mean")]
    private static extern double mean(double x, double y);

    [DllImport("libtestmachw.dylib")]
    private static extern int OPEN_IMAGE_FILE(string fileName);

    [DllImport("libtestmachw.dylib")]
    private static extern int OpenImageFile(string fileName);
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");
        Console.WriteLine("Let's try to communicate with a Mac dylib library");
        Console.WriteLine("We are now going to invole function 'mean' of libtestmacw.dylib");
        try
        {
            double result = mean(2, 4);
            Console.WriteLine("yes, we made it! Result:" + result);
        }
        catch (Exception e)
        {
            Console.WriteLine("Opes that didn't work!");
            Console.WriteLine(e);

        }
        Console.WriteLine("We are now going to invole function 'OPEN_IMAGE_FILE' of libtestmacw.dylib");
        try
        {
            int result = OPEN_IMAGE_FILE("SomeFile.png");
            Console.WriteLine("yes, we made it! Result:" + result);
        }
        catch (Exception e)
        {
            Console.WriteLine("Opes that didn't work!");
            Console.WriteLine(e);

        }
        Console.WriteLine("We are now going to invole function 'OpenImageFile' of libtestmacw.dylib");
        try
        {
            int result = OpenImageFile("SomeFile.png");
            Console.WriteLine("yes, we made it! Result:" + result);
        }
        catch (Exception e)
        {
            Console.WriteLine("Opes that didn't work!");
            Console.WriteLine(e);

        }
        Console.ReadLine();
    }

When running this, on Mac, I get an System.EntryPointNotFoundException

Unable to find an entry point named 'OpenImageFile' in DLL 'libtestmachw.dylib'.

I just want to test if I can import functions inside a .NETCore application, from their on I can instruct the Chinese company to get their code compiled into a .dylib . Who can help me out or point me into the right direction?

This Microsoft page shows it is possible, so I am guess I am doing something wrong at the c/c++ side? https://docs.microsoft.com/en-us/dotnet/standard/native-interop

You cannot call C++ functions, only C functions. Also, these functions need to be exported using standard C conventions, so in C++ you might need to add an extern "C" as well.

The problem in your sample is that TAPIFunc::OpenImageFile is a C++ function that cannot be imported.

For example, this function defined in a .cpp file can be used in .NET Core:

extern "C" int32_t Bridge_OpenFile(char* filename) {
    // you can do some C++ calls here
    return 0;
}

using

[DllImport("my.dylib")]
private static extern int Bridge_OpenFile([MarshalAs(UnmanagedType.LPStr)]string filename);

Another trick: DllImport can be used with just testmachw since CoreCLR will add lib and .dylib automatically as part of the probing so you can have the same C# code and it will match lib{foo}.dylib , lib{foo}.so and {foo}.dll depending on the platform run on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM