简体   繁体   中英

Do you need a separate [DllImport(...)] for each function in C# when importing from a C++ DLL?

I am experimenting with DLLs to try and design a wrapper around a C++ library that allows class objects to be used in C# applications.

I am using System.Runtime.InteropServices to import functions one by one into my C# program as follows:

Program.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
    internal class Program
    {
        [DllImport(@"..\..\..\Project1\x64\Debug\Project1.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int AddNumbers(int a, int b);
        [DllImport(@"..\..\..\Project1\x64\Debug\Project1.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int SubtractNum(int a, int b);

        [DllImport(@"..\..\..\Project1\x64\Debug\Project1.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr Foo_Create(int a, int b);
        public static extern int Foo_getFoo(IntPtr pFoo);
        [DllImport(@"..\..\..\Project1\x64\Debug\Project1.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Foo_addBar(IntPtr pFoo, int a);
        [DllImport(@"..\..\..\Project1\x64\Debug\Project1.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int Foo_Delete(IntPtr pFoo);

        static void Main(string[] args)
        {
            int output = AddNumbers(5, 11);
            int output2 = SubtractNum(11, 5);
            Console.WriteLine($"Output: {output} - {output2}");

            IntPtr foo = Foo_Create(6, 6);
            Console.WriteLine($"Expect 6, got: {Foo_getFoo(foo)}");
            Console.WriteLine($"Expected 10, got: {Foo_addBar(foo, 4)}");
            Foo_Delete(foo);
            Console.ReadLine();
        }
    }
}

Is there a more concise way to import these functions than having to have a separate DllImport() for each one? When I remove one, I see the warning "Method, operator, or accessor 'method' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation." so I assume it is necessary.

For reference the c++ file that I am compiling into a DLL is as follows:

#define DllExport   __declspec( dllexport )

extern "C" {
    DllExport int AddNumbers(int a, int b) {
        return a + b;
    }
    DllExport int SubtractNum(int a, int b) {
        return a - b;
    }
}

class DllExport Foo {
    public:
        Foo(int a, int b) {
            foo = a;
            bar = b;
        }
        int getFoo() { return foo; };
        int addBar(int a) { return private_method(a); };
    private:
        int private_method(int a) { return a + bar; };
        int foo;
        int bar;
};

// Wrapper functions to provide access to class methods that should be available to client
extern "C" DllExport Foo * Foo_Create(int a, int b) { return new Foo(a, b); }
extern "C" DllExport int Foo_getFoo(Foo * pFoo) { return pFoo->getFoo(); }
extern "C" DllExport int Foo_addBar(Foo * pFoo, int a) { return pFoo->addBar(a); }
extern "C" DllExport void Foo_Delete(Foo * pFoo) { delete pFoo; }

If your library has functions like this then yes, you have to DllImport each separately.

If you control the DLL, you could add a function that returns a structure containing function pointers (or pointer to such a structure) and then import just that function. That is basically what COM interop does, simply hiding where the structure comes from.

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