2017-03-24 2 views
0

Donc, c'est un projet simple que je mets juste pour tester avant de faire quelques trucs cool avec ça plus tard. L'objectif final est de rendre le programme capable de gérer la modularité grâce à un impressionnant dll kung fu.Comment lier un DLL personnalisé dans Ada?

Mais, bébé étapes. En ce moment je veux juste faire le lien de chose.

Ici, j'ai Adder.ads:

package Adder is 

    function Add(A : Integer; B : Integer) return Integer; 

end Adder; 

Et le Adder.adb respectif:

package body Adder is 

    function Add(A : Integer; B : Integer) return Integer is 
    begin 
     return A + B; 
    end Add; 

end Adder; 

excitant, je sais.

Je l'ai vu plusieurs tutoriels différents sur la façon de le faire, et aucun d'entre eux sont d'accord, mais en prenant un signal de this one, je suis venu avec ces commandes:

gnatmake -c Adder.adb 
gcc -shared -shared-libgcc -o Adder.dll Adder.o 

Ce au moins génère un dll. Je ne sais pas si elle génère un qui fonctionnera réellement ou si le problème est avec l'exe principal cependant.

Maintenant l'exe principal, j'ai tout gardé dans un répertoire séparé afin que gnat n'essaie pas de tricher et d'utiliser les fichiers .ali et .o. Ensuite, vous copiez la DLL dans le répertoire avant d'essayer de construire. J'ai essayé ce truc de différentes façons et j'ai eu plusieurs erreurs différentes, mais voici ce que j'ai en ce moment.

Main.adb:

with Adder_Spec; use Adder_Spec; 
with Ada.Text_IO; use Ada.Text_IO; 

procedure Main is 
begin 
    Put_Line(Integer'Image(Add(3,4))); 
end Main; 

Yay programme le plus inutile jamais. Maintenant, sachant que je suis censé avoir une spécification pour la dll, je suis venu avec les Adder_Spec.ads aforewith'd:

package Adder_Spec is 

    function Add(A : Integer; B : Integer) return Integer; 

private 

    pragma Import(Ada, Add, "Add"); 

end Adder_Spec; 

Maintenant, comme je l'ai dit que je l'ai essayé ce un tas de façons différentes, en omettant parfois le troisième paramètre d'importation, d'autres fois en omettant complètement l'importation, en gardant parfois l'importation mais en ne la séparant pas dans la partie privée, vous le nommez. J'ai aussi essayé de jouer avec la commande de compilation de plusieurs façons, mais voici le plus récent:

gnatmake Main.adb -bargs -shared -largs -lAdder 

Avec cette commande particulière, il recrache une « référence non définie à « Ajouter » » erreur. Si j'ajoute l'indicateur -v, cela ne fournit pas beaucoup plus d'informations utiles.

La vérification de gnatmake --help me montre que le mode par défaut est gnat 2012, si cela fait une différence. Il ne devrait probablement pas, comme j'ai essayé de compiler avec les drapeaux pour 2005 et 95, aussi.

Alors ... quelqu'un peut-il assez bien repérer le problème? Merci d'avance.

+0

Techniquement, il s'agit d'une question GNAT et non d'une question Ada (mais je pense que garder la balise "ada" est la plus rationnelle de toute façon). –

+1

Quand vous dites 'gcc -shared -shared-libgcc -o Adder.dll -Adder.o', je pense que vous voulez dire simplement 'Adder.o'? –

+0

@SimonWright Oui, bonne prise. – Devsman

Répondre

3

Si vous voulez dire

package Adder_Spec is 
    function Add(A : Integer; B : Integer) return Integer; 
private 
    pragma Import(Ada, Add, "Add"); 
end Adder_Spec; 

lors de l'importation de la DLL, alors vous devez dire

package Adder is 
    function Add(A : Integer; B : Integer) return Integer; 
    pragma Export (Ada, Add, "Add"); 
end Adder; 

lors de sa création.

Le nom de l'éditeur de liens par défaut de GNAT pour le Add généré serait (je pense) adder__add; vous devriez être en mesure de voir ce qu'il utilise nm Adder.o.

+0

AFAIK une exportation pragma doit être déclarée immédiatement après la définition du contrat importé: il ne reste aucune ambiguïté concernant sa portée. Avec l'exportation déclarée en partie privée et le contrat en partie publique, quel serait le comportement attendu de toute façon? Et pourquoi une telle construction est nécessaire? – LoneWanderer

+0

@LoneWanderer - Si vous cochez [ARM05 B.1 (51)] (http://www.adaic.org/resources/add_content/standards/05rm/html/RM-B-1.html#p51), vous verrez l'exportation déclarée dans la partie privée. J'imagine qu'il pourrait y avoir un problème si vous utilisiez un sous-programme avant de voir le pragma, peut-être en déclarant une variable initialisée au résultat d'un appel de fonction; l'idée ici et dans l'exemple ci-dessus doit être de cacher les détails désordonnés aux yeux de ceux qui n'ont vraiment pas besoin de savoir. De nos jours, bien sûr, les aspects 'Convention',' Export' et 'External_Name' sont dans votre visage! –

+0

Vous da man, Simon. J'aurais dû deviner que c'était ça. – Devsman

0

Je vous suggère de suivre les instructions de la section "Ada Plug-ins et bibliothèques partagées" (part 1, part 2) d'AdaCore.

J'ai utilisé la technique décrite ici, et cela a très bien fonctionné.

+0

Je vais certainement regarder cela plus de; Merci! – Devsman