2
votes

Appel de programmes C # à partir de D

Comment puis-je appeler des fonctions C # (une DLL) à partir de D?

J'ai essayé ou je regarde ce qui suit:

L'approche Derelict Mono fonctionne bien pour les programmes Hello World, mais une DLL plus volumineuse (avec des références à de nombreux autres assemblys, dont chacun peut ou non utiliser des appels d'API Windows authentiques) échoue car la DLL n'est pas correctement chargée.

/ p>

Les expériences initiales avec les exportations non gérées entraînent des erreurs avec MSBUILD.


0 commentaires

3 Réponses :


1
votes

J'ai une chaîne préliminaire passant la solution de D à (une petite quantité de) C ++ vers C # basée sur les articles suivants: (j'ai abandonné les exportations non gérées de Robert Giesecke)

C # "Unmanaged Exports" (tutoriel de Hans Passant)

Appel de la fonction C # depuis C ++ / CLI - Convertir la chaîne Return C # en C String

L'intégration D à C ++ avec Visual D fonctionne.

https://rainers.github.io/visuald/visuald/vcxproject.html (Voir Intégration de projet Visual C / C ++)

https://dlang.org/spec/cpp_interface.html


0 commentaires

1
votes

Essayez ce qui suit. D'abord le code D:

gcbuf = GCHandle.Alloc(buffer, GCHandleType.Pinned);
ulong l = (ulong)gcbuf.AddrOfPinnedObject();

Puis un shim C ++ / CLI:

using System.Runtime.InteropServices;
using System.Text;

namespace CS_Interop {

    public class Test {

        public static byte[] buffer;

        public static GCHandle gcbuf;

        public static ulong receiveMe(ulong arg) {
            string s = "I was a string " + arg;
            s = (s.Length + 2) + s;
            buffer = Encoding.ASCII.GetBytes(s);
            gcbuf = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            ulong l = (ulong)gcbuf.AddrOfPinnedObject();
            return l;
        }

        public static ulong freeMe(ulong arg) {
            gcbuf.Free();
            return 42;
        }
    }
}

Enfin le C #:

#include "stdafx.h"
#using "...\CS-Interop\bin\x64\Debug\netstandard2.0\CS-Interop.dll"

using namespace System;

UInt64 sendMe(UInt64 arg) {
    return CS_Interop::Test::receiveMe(42);
}

UInt64 freeMe(UInt64 arg) {
    return CS_Interop::Test::freeMe(42);
}

Je cherche toujours des moyens de me débarrasser de ce shim C ++ / CLI.

Ce code est écrit de telle manière que vous pouvez fouiller avec le débogueur VS.

Ceci est très simple à configurer et à tester dans Visual Studio. Avec Visual D installé, commencez par configurer un projet C ++ / CLI (PAS un projet Visual D) et placez le code D et C ++ là. Ensuite, configurez un projet DLL C # sous le projet D.

C'est une chose d'appeler du code C # à partir de D, mais une autre chose de récupérer des données à moins que vous n'utilisiez uniquement des types scalaires simples comme int. Les lignes clés de C # sont

module main;
import std.stdio;
import std.conv;

extern (C++) ulong receiveMe(ulong i);
extern (C++) ulong freeMe(ulong i);

void main() {
    ulong l = receiveMe(0);
    char* p = cast(char*)l;
    char[] s = to!(char[])(p);
    byte[] b = cast(byte[])(s.dup);
    writeln("The answer is " ~ to!string(s));
    ulong m = freeMe(0);
}

où vous devez d'abord épingler l'objet que vous renvoyez puis renvoyer l'adresse à D. Il y a pas de travail fastidieux avec le marshaling dans la partie C ++, votre code D doit juste être capable de gérer tout ce qui se trouve derrière le pointeur.

Assurez-vous également de libérer le pointeur épinglé une fois que vous en avez terminé . Mettez en commentaire la ligne freeMe dans le code D et regardez l'utilisation de la mémoire augmenter (et augmenter) dans VS.

Personnellement, je trouve le processus pin un peu instable car GCHandle.Alloc ne fonctionnera que lorsque son premier argument, que ce soit un tableau d'octets ou une structure , contient des éléments blittables .

Voir aussi https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types


1 commentaires

Merci pour cela. Avec quelques changements, cela a plutôt bien fonctionné pour moi.



1
votes

Vous pouvez utiliser des exportations non gérées pour appeler C # depuis D. Je l'ai fait sans problème.

Voir https://sites.google.com/site/robertgiesecke/ Accueil / importations / exportations non gérées

Cependant, lorsque j'ai essayé les exportations non gérées avec Visual Studio 2017, je ne pouvais pas non plus le faire fonctionner. Les exportations non gérées fonctionnaient bien avec VS2015. Étant donné que le lien date de juillet 2009, d'autres aspects auraient pu devenir obsolètes.

Lisez attentivement les instructions et surtout assurez-vous que vous construisez pour x86 ou x64, et non pour "n'importe quel processeur". Le rassemblement des données sera un autre défi.


0 commentaires