Export funkcji poprzez bibliotekę DLL

0

Czy możliwe jest aby wyeksportować funkcję i użyć ją w innym języku takim jak C++? Bibliotekę kompilowałem z Unmanaged Exports i C# ale nie da się tego użyć w C++.

title

0

Jest możliwość użycia biblioteki napisanej w C# (normalnie napisanej, bez kombinowania) w C++/CLI.
Visual C++ pozwala włączyć tryb C++/CLI dla pojedynczego pliku .cpp w projekcie, nie trzeba koniecznie od razu całego projektu kompilować jako C++/CLI.
W tym jednym .cpp będzie wtedy dostęp do klas z C#.

0

Tylko nie wiem czy to u mnie przejdzie bo program był pisany i kompilowany w GCC. Czyli jednak nie da się tak wyeksportować funkcji z biblioteki tak jak w C++?

1

tl;dr
U mnie działa. Pierwsza rzecz, jaka mi się rzuciła w oczy - pamiętasz, że Class Library musi być x86 albo x64, a nie Any CPU - masz tak zrobione? Głupi błąd, ale często się o tym zapomina. Używam VS2017, a nie Xamarin Studio, nie wiem czy Xamarin Studio poprawnie radzi sobie z dodatkowymi skryptami w NuGetach.

Zasadniczo dotychczas uważałem, że się nie da wyeksportować funkcji z .NET-owego assembly dla aplikacji natywnych.

Przejrzałem jednak tego UnmanagedExports i działa... dziwnie. Bo kiedy stworzyłem sobie dwie funkcje, w tym jedną taką, jak Twoja, to według Dll Export Viewer nie ma tam nic. Jednak z kolei dumpbin, PEInfo oraz FileAlyzer już pokazuje poprawnie oba eksporty, więc, wierzę, że jednak tam są ;-)

Niby sam skrypt przy budowaniu projektu coś tam robi:

1>  Found method: ClassLibrary1.Class1..method public hidebysig static void  'Test'(int32 'a') cil managed
1>  Removing RGiesecke.DllExport.DllExportAttribute from ClassLibrary1.Class1.Test
1>  	old declaration: .method public hidebysig static void  'Test'(int32 'a') cil managed
1>  	new declaration: .method public hidebysig static void modopt(['mscorlib']'System.Runtime.CompilerServices.CallConvStdcall')  'Test'(int32 'a')
1>  	exporting as Test and index 1
1>  Deleting unused reference to RGiesecke.DllExport.Metadata.
1>  Parsing 114 lines of IL took 25 ms.

Potem napisałem bardzo skomplikowany program, używając mojego braku skilli do C++, i zadziałało!

#include "stdafx.h"
#include <Windows.h>

int main()
{
	typedef int(CALLBACK* LPFNDLLFUNC1)(int);
	typedef char*(CALLBACK* LPFNDLLFUNC2)(char*);

	HINSTANCE hDLL;               // Handle to DLL
	LPFNDLLFUNC1 lpfnDllFunc1;    // Function pointer	
	LPFNDLLFUNC2 lpfnDllFunc2;
	int  uParam2, uReturnVal;

	hDLL = LoadLibrary(L"ClassLibrary1");
	if (hDLL != NULL)
	{
		lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,
			"Test");
		if (!lpfnDllFunc1)
		{
			// handle the error
			FreeLibrary(hDLL);
			return 3;
		}
		else
		{
			// call the function
			uReturnVal = lpfnDllFunc1(3);
			printf("%d", uReturnVal);
		}

		lpfnDllFunc2 = (LPFNDLLFUNC2)GetProcAddress(hDLL,
			"ImageToBase64");
		if (!lpfnDllFunc2)
		{
			// handle the error
			FreeLibrary(hDLL);
			return 4;
		}
		else
		{
			// call the function			
			printf("%s", lpfnDllFunc2("E:\\Marcin\\Temp\\a.txt"));
		}
	}

	return 0;
}

A biblioteka C# wygląda następująco:

using RGiesecke.DllExport;
using System;

namespace ClassLibrary1
{
    public static class Class1
    {
        [DllExport(CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall, ExportName = "ImageToBase64")]
        public static string ImageToBase64(string filename)
        {
            var arr = System.IO.File.ReadAllBytes(filename);
            return Convert.ToBase64String(arr);
        }

        [DllExport(CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall, ExportName = "Test")]
        public static int Test(int a)
        {
            return 4;
        }
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1