2013-01-18 32 views
10

लंबे समय श्रोता, पहली बार कॉलर के साथ साझा किया। मुझे पता है कि यह कुछ हद तक अस्पष्ट सवाल है, और बहुत ज्यादा उम्मीद नहीं है। :-)लोडिंग एडी ने पर्ल में DynaLoader.pm

मैं निम्नलिखित एडीए फ़ाइलें:

greeter.ads

package Greeter is 
    procedure Hello; 
end Greeter; 

greeter.adb

with Ada.Text_IO; use Ada.Text_IO; 
package body Greeter is 
    procedure Hello is 
    begin 
     Put_Line ("Hello, world!"); 
    end Hello; 
end Greeter; 

और उनकी तरह एक साझा वस्तु में संकलन यह:

gnatmake -z -fPIC greeter.adb 
gcc -shared -o libgreeter.so greeter.o 

यह ठीक संकलित करता है।

$ nm -D libgreeter.so 
       w _Jv_RegisterClasses 
0000000000201028 A __bss_start 
       w __cxa_finalize 
       w __gmon_start__ 
       U __gnat_eh_personality 
0000000000201028 A _edata 
0000000000201038 A _end 
00000000000006a8 T _fini 
0000000000000520 T _init 
       U ada__text_io__put_line__2 
0000000000201018 D greeter_E 
000000000000063c T greeter__hello 

अब मैं पर्ल में है कि साझा वस्तु लोड करने का प्रयास:

#!/usr/bin/env perl 

use 5.014; 
use strict; 
use warnings; 

#BEGIN { $ENV{PERL_DL_DEBUG} = 1 }; 

package Greeter 
{ 
    use constant ADADIR => '/usr/lib/gcc/x86_64-linux-gnu/4.4/rts-native/adalib/'; 
    use constant OURDIR => do { (my $f = __FILE__) =~ s{[^/]+$}//; $f || "." }; 

    require DynaLoader; 
    our @ISA = 'DynaLoader'; 

    my $runtime = DynaLoader::dl_load_file(
     ADADIR.'/libgnat.so', 
    ) or die DynaLoader::dl_error(); 

    my $gep = DynaLoader::dl_find_symbol(
     $runtime, 
     '__gnat_eh_personality', 
    ) or die DynaLoader::dl_error(); 

    my $libref = DynaLoader::dl_load_file(
     OURDIR.'/libgreeter.so', 
     0x01, 
    ) or die DynaLoader::dl_error(); 

    my $func = DynaLoader::dl_find_symbol(
     $libref, 
     'greeter__hello', 
    ) or die DynaLoader::dl_error(); 

    print $func, $/; 
} 

लेकिन निम्न संदेश के साथ बाहर इस बम:

./libgreeter.so nm निम्नलिखित प्रतीक से पता चलता : अपरिभाषित प्रतीक: __gnat_eh_personality at ./greeter.pl लाइन 26.

क्या किसी के पास कोई संकेत है? क्या डायनालोडर से कुछ बेहतर/आसान है जिसका उपयोग करना चाहिए ??

उत्तर

9

मैं पर्ल पक्ष में मदद नहीं कर सकता (आपको 5.14 की आवश्यकता है, मैक ओएस एक्स में 5.12 है, डेबियन 6 में 5.10 है)। उस ने कहा, मैं सी मुख्य और सीधा लिंकिंग के लिए लाइब्रेरी बनाने में मदद कर सकता हूं ...

जीएनएटी बिल्ड प्रक्रिया पर्याप्त जटिल है कि इसका समर्थन करने के लिए दो टूल्स हैं, gnatmake और gprbuild। यह संभव है (सितंबर 2015 को लिखना) कि gnatmake लाइब्रेरी बनाने की क्षमता खो देगा, इसलिए gprbuild बेहतर विकल्प है।

मैं तुम्हें एक स्टैंड-अलोन पुस्तकालय परियोजना (अर्थात, प्रारंभ और अंतिम रूप देने के कार्य है कि एडीए विस्तार पर नियंत्रण के साथ एक है की जरूरत है, यदि आप एडीए पुस्तकालय को प्रारंभ नहीं है, आप SEGVs या अन्य बुरे मिलेगा व्यवहार)। आपको एक here बनाने पर कम डाउनडाउन मिलेगा।

greeter.gpr मैंने लिखा

project Greeter is 
    for Library_Name use "greeter"; 
    for Library_Kind use "relocatable"; 
    for Library_Dir use "lib"; 
    for Library_Interface use ("greeter"); 
    for Library_Auto_Init use "true"; -- the default, I think 
    for Object_Dir use ".build"; -- to keep temp objects out of the way 
end Greeter; 

Library_Name विशेषता पुस्तकालय के नाम को नियंत्रित करता है, लिनक्स पर मैक ओएस एक्स, libgreeter.so पर libgreeter.dylib

Library_Kind विशेषता वैकल्पिक रूप से "static" हो सकती है, इस मामले में नाम libgreeter.a होगा। हालांकि, स्टैंड-अलोन लाइब्रेरी स्थानांतरित होनी चाहिए।

Library_Dir विशेषता, जिसे आपको लाइब्रेरी बनाने के लिए (उपरोक्त दो के साथ) आपूर्ति करना है, पुस्तकालय बनाया गया है, जहां नियंत्रण होता है; इस मामले में, lib/ में।

आपको इसे स्टैंड-अलोन लाइब्रेरी बनाने के लिए Library_Interface विशेषता प्रदान करना है और प्रारंभिकता और अंतिमकरण संचालन उत्पन्न करना है जो एडा विस्तार को नियंत्रित करता है। , greeterfinal यहाँ, greeterinit - वे लाइब्रेरी कहा जाता है init और लाइब्रेरीfinal

यदि Library_Auto_Init"false" है तो आपको "true" पर प्रारंभिकरण और अंतिमकरण संचालन स्वयं को कॉल करना होगा, तो वे स्वचालित रूप से प्रबंधित होते हैं।

ठीक है, (-p कहते हैं "कोई भी आवश्यक उत्पादन निर्देशिका बनाएं", -P प्रोजेक्ट फ़ाइल निर्दिष्ट करता है)

gprbuild -p -P greeter 

द्वारा पुस्तकालय का निर्माण।

मैं greeter.c

#include <stdio.h> 

extern void greeter_hello(); 

int main() 
{ 
    greeter__hello(); 
    return 0; 
} 

बनाया

$ gcc greeter.c -o greeter -L lib -l greeter 

और रन (लिनक्स पर)

$ LD_LIBRARY_PATH=./lib ./greeter 
+0

साइमन राइट का उपयोग कर ++ का उपयोग करते हुए, इस मुझे कुछ अच्छी चीजें साथ आरंभ करने के लिए दे दिया है। मैं इसे आज़माउंगा और यदि यह काम करता है, तो यह जवाब स्वीकार करेगा। – tobyink

+0

मेरे पास अभी तक कोशिश करने के लिए ट्यूट्स नहीं हैं, लेकिन इस बीच में मैंने जवाब स्वीकार कर लिया है क्योंकि यह अब तक दोनों का अधिक आशाजनक प्रतीत होता है। – tobyink

4

मैं इस के साथ सबसे अच्छा मैं कर सकते हैं करेंगे, बहुत ज्यादा नहीं पर्ल ज्ञान दिया:

मैं सभी प्रासंगिक यहाँ फाइलों के साथ भंडार है।

मुझे लगता है कि Dynaloader पर perl एक उपयोगिता है जो आपको गतिशील रूप से लोड करने योग्य लाइब्रेरी (lib * .so यूनिक्स सिस्टम पर) को एक पर्ल प्रोग्राम में लोड करने देती है।

इसके लिए एक एडीए प्रोग्राम के लिए काम करने के लिए, आपको कई चीजों को ध्यान में रखना होगा।

  1. आपको अपने एडीए प्रोग्राम को उचित गतिशील पुस्तकालय के रूप में बनाने की आवश्यकता है। ऐसा लगता है कि आपने ऐसा किया था। हालांकि, मैं इस पर कोई विशेषज्ञ नहीं हूं, इसलिए शायद आप कुछ चूक गए। मैं इस पर टीएफएम को देखने का सुझाव देता हूं।
  2. आपको अपने एडीए कोड को सही तरीके से कॉल करने की आवश्यकता है। एडीए कार्यक्रमों को आम तौर पर किसी भी वास्तविक कोड को चलाने से पहले "विस्तार" नामक प्रक्रिया की आवश्यकता होती है। इसे पूरा करने के लिए, अधिकांश एडा कंपाइलर आपके "मुख्य" दिनचर्या से जुड़े किसी एक का उपयोग करने के बजाय प्रोग्राम में एक विशेष प्रविष्टि-बिंदु बनाते हैं। मुझे लगता है कि गानाट C_yourprogramname जैसा कुछ है, लेकिन मुझे उस पर पकड़ न दें। भले ही आप किसी प्रकार की लाइब्रेरी को कार्यान्वित कर रहे हों, फिर भी विस्तार पहले चलाया जाना चाहिए (कुछ विशेष परिस्थितियों में निष्पादित करें, जो यहां लागू नहीं होते हैं)। हालांकि, अगर आप नियमित रूप से एडा के बाहर से एक लाइब्रेरी दिनचर्या चाहते हैं, तो आप आमतौर पर "मुख्य" नहीं चाहते हैं, इसलिए कुछ अतिरिक्त कदम हैं।जीएनएटी के साथ यह कैसे करें described in their user guide है, लेकिन आम तौर पर इसमें कंपाइलर को "मुख्य" बनाने के लिए कहा जाता है, जो adainit को बाहर से किसी भी एडा रूटीन चलाने से पहले कॉल करता है, और adafinal पर कॉल करने पर कॉल करता है।