Changeset 98

Show
Ignore:
Timestamp:
01/02/06 05:01:50 (3 years ago)
Author:
Don Clugston
Message:

Dynamic library: added a clean interface for dynamically loading classes. Currently requires that an interface be used; only 0-2 constructor parameters are included at present (it is trivial to add more).
Fold in changes for DMD 0.142 (many fewer hacks required in 'meta' library).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ddl/DynamicLibrary.d

    r94 r98  
    6868    public bit isCModule(){ 
    6969        return true; 
    70     } 
    71              
    72     public void* getExportAddress(char[] name){ 
    73         return this.getExport(name).address; 
    74     } 
     70    }    
     71 
     72    // Dynamic loading of non-class objects, including static functions 
    7573     
    7674    template getDExport(T, char [] name) { 
    7775        static if(T.mangleof[0] == 'P'){ 
    78             typeof(T) getDExport() { return cast(typeof(T))getExportAddress( "_D" ~  mangleText!(name) ~ sliceheadoff!(T.mangleof, 1)); } 
    79         } else{ 
    80             typeof(T) getDExport() { return cast(typeof(T))getExportAddress("_D" ~  mangleText!(name) ~ T.mangleof); } 
    81         } 
    82     } 
    83     /* 
    84     TODO: investigate the proper mangle code for these 
    85      
    86     template getClassInfo(char[] classname){ 
    87         ClassInfo getClassinfo(){ 
    88             return cast(ClassInfo)getExportAddress("__Class_" ~  mangleText!(name)); 
     76            typeof(T) getDExport() { 
     77                return cast(typeof(T))getExport( "_D" ~  mangleSymbolName!(name) ~ sliceheadoff!(T.mangleof, 1)).address;  
     78                } 
     79        } else { 
     80            typeof(T) getDExport() { 
     81            return cast(typeof(T))getExport("_D" ~  mangleSymbolName!(name) ~ T.mangleof).address; } 
    8982        } 
    9083    } 
    9184     
    92     template getCtor(Tfn, char[] classname){ 
    93        typeof(Tfn) getCtor(){  
    94            //TODO: hack up the mangleof of Tfn, to replace the return type as the correct type. 
    95             return cast(typeof(Tfn))getExportAddress( "_D" ~  mangleText!(classname) ~ "_ctor" ~ Tfn.mangleof ~  mangleText!(classname));  
     85    /// Load the ClassInfo corresponding to classname. 
     86    template getClassInfo(char[] classname){ 
     87        ClassInfo getClassInfo(){ 
     88            return cast(ClassInfo)getExport("__Class_" ~  mangleSymbolName!(classname)).address; 
    9689        } 
    9790    } 
     91    /**   TInterface function(P1)  getCtor!(TInterface, classname, P1); 
     92     * 
     93     *  Returns a function which constructs a class, using the given parameters. 
     94     *  For example: 
     95     *  ------------ 
     96     *  auto newFoo = getCtor("FooModule.Foo", char [], real); 
     97     *  auto newFooI = getCtor("FooModule.Foo", int); 
     98     *  x = newFooI(58); 
     99     *  y = newFoo("Avogadro's Number", 6.022e23); 
     100     * ----------------- 
     101     *  is equivalent to: 
     102     * ----------------- 
     103     *  x = new FooModule.Foo(58); 
     104     *  y = new FooModule.Foo("Avogadro's Number", 6.022e23); 
     105     * ----------------- 
     106     */ 
     107    // TODO: might be better to return a delegate? 
     108    template getCtor(TInterface, char [] classname) { 
     109        TInterface function() getCtor() { 
     110            static ClassInfo typeClass; 
     111            typeClass = getClassInfo!(classname)(); 
     112            static Object function (Object) rawCtor; 
     113            rawCtor = cast(Object function (Object)) getExport( 
     114                "_D" ~ mangleSymbolName!(classname) ~ mangleSymbolName!("_ctor")  
     115                ~ "F" 
     116                ~ "ZC" ~ mangleSymbolName!(classname)).address;      
     117            static TInterface internalCtor() { 
     118                  auto a = _d_newclass(typeClass); 
     119                  rawCtor(a); 
     120                  return cast(TInterface)a; 
     121           } 
     122         
     123           return &internalCtor; 
     124       } 
     125    } 
    98126     
    99     template createObject(char[] classname){ 
    100         Object createObject(){ 
    101             auto typeClass = getClassInfo!(classname)(); 
    102             auto objClass = _d_newclass(typeTestClass); 
    103             auto ctorClass = getCtor!(Object function(Object),classname)(); 
    104             return ctorClass(objClass); 
    105         } 
    106     }*/ 
     127    template getCtor(TInterface, char [] classname, P1) { 
     128        TInterface function(P1) getCtor() { 
     129            static ClassInfo typeClass; 
     130            typeClass = getClassInfo!(classname)(); 
     131            static Object function (P1, Object) rawCtor; 
     132            rawCtor = cast(Object function (P1, Object)) getExport( 
     133                "_D" ~ mangleSymbolName!(classname) ~ mangleSymbolName!("_ctor")  
     134                ~ "F" ~ P1.mangleof  
     135                ~ "ZC" ~ mangleSymbolName!(classname)).address;      
     136            static TInterface internalCtor(P1 p1) { 
     137                  auto a = _d_newclass(typeClass); 
     138                  rawCtor(p1, a); 
     139                  return cast(TInterface)a; 
     140           } 
     141         
     142           return &internalCtor; 
     143       } 
     144    } 
     145    template getCtor(TInterface, char [] classname, P1, P2) { 
     146        TInterface function(P1, P2) getCtor() { 
     147            static ClassInfo typeClass; 
     148            typeClass = getClassInfo!(classname)(); 
     149            static Object function (P1, P2, Object) rawCtor; 
     150            rawCtor = cast(Object function (P1, P2, Object)) getExport( 
     151                "_D" ~ mangleSymbolName!(classname) ~ mangleSymbolName!("_ctor")  
     152                ~ "F" ~ P1.mangleof ~ P2.mangleof 
     153                ~ "ZC" ~ mangleSymbolName!(classname)).address;      
     154            static TInterface internalCtor(P1 p1, P2 p2) { 
     155                  auto a = _d_newclass(typeClass); 
     156                  rawCtor(p1, a); 
     157                  return cast(TInterface)a; 
     158           } 
     159         
     160           return &internalCtor; 
     161       } 
     162    } 
    107163} 
  • trunk/ddl/Mangle.d

    r94 r98  
    3838import meta.strhacks; 
    3939 
    40 template mangleText(char[] text, char [] latestword="") 
     40/**  char [] mangleSymbolName!(char [] name); 
     41 *  Convert a name of the form "module.func" to the form 
     42 *  "6module4func". 
     43 */ 
     44template mangleSymbolName(char[] text, char [] latestword="") 
    4145{ 
    4246  static if (text.length<1)  { 
    43      static if (strlen!(latestword)==0) 
    44             const char[] mangleText = ""; 
    45      else const char[] mangleText = itoa!(strlen!(latestword)) ~ latestword; 
     47     static if (latestword.length==0) 
     48            const char[] mangleSymbolName = ""; 
     49     else const char[] mangleSymbolName = itoa!(latestword.length) ~ latestword; 
    4650  } else static if (text[0]=='.') { 
    47       const char[] mangleText
    48       itoa!(strlen!(latestword)) ~ latestword ~ .mangleText!(slice!(text, 1, strlen!(text)), ""); 
     51      const char[] mangleSymbolName
     52      itoa!(latestword.length) ~ latestword ~ .mangleSymbolName!(text[1..(text.length)], ""); 
    4953  } else 
    50      const char[] mangleText = .mangleText!( slice!(text, 1, strlen!(text)), concat!(latestword,slice!(text, 0, 1))); 
     54     const char[] mangleSymbolName = .mangleSymbolName!( text[1..(text.length)], concat!(latestword,text[0..(1)])); 
    5155}  
  • trunk/meta/conv.d

    r89 r98  
    44  * so most of these functions have unique names. 
    55  * Compile with -version=testmeta to run unit tests. 
     6  * Author: Don Clugston. License: Public domain. 
    67  */ 
    78   
     
    1920template itoa(long n) 
    2021{ 
    21          static if (n<0)  const char [] itoa = "-" ~ .itoa!(-n);  
    22    else  static if (n<10L) const char [] itoa = decimaldigit!(n); 
    23    else  const char [] itoa = .itoa!(n/10L) ~ decimaldigit!(n%10L); 
     22    static if (n<0) { 
     23        const char [] itoa = "-" ~ .itoa!(-n);  
     24    } else static if (n<10L) { 
     25        const char [] itoa = decimaldigit!(n); 
     26    } else { 
     27        const char [] itoa = .itoa!(n/10L) ~ decimaldigit!(n%10L); 
     28    } 
    2429} 
    2530 
    2631template toHexString(ulong n) 
    2732{ 
    28    static if (n<16L) const char [] toHexString = hexdigit!(n); 
    29    else  const char [] toHexString = .toHexString!(n >> 4) ~ hexdigit!(n&0xF); 
     33    static if (n<16L) { 
     34        const char [] toHexString = hexdigit!(n); 
     35    } else { 
     36        const char [] toHexString = .toHexString!(n >> 4) ~ hexdigit!(n&0xF); 
     37    } 
    3038} 
    3139 
     
    3745  static if (s.length==indx) const long atoi=sofar; 
    3846  else static if (indx==0 && s[indx]=='-') const long atoi = -.atoi!(s, 0, 1); 
    39   else static if (!isdigit!( getcharat!(s, indx) ) ) const long atoi = sofar; 
    40   else const long atoi = .atoi!(s, sofar * 10 + (getcharat!(s, indx)-'0'), indx+1); 
     47  else static if (!isdigit!( cast(char) s[indx] ) ) const long atoi = sofar; 
     48  else const long atoi = .atoi!(s, sofar * 10 + s[indx]-'0', indx+1); 
    4149} 
    4250 
    4351/******************************************************* 
    44  *  the number of digits which would be 'consumed' by atoi!(). 
     52 *  the number of characters in s[] which would be 'consumed' by atoi!(). 
    4553 */ 
    4654template countleadingdigits(char [] s, int indx=0) 
    4755{ 
    48   static if (s.length==indx) const int countleadingdigits=indx; 
    49   else static if (indx==0 && s[indx]=='-') const int countleadingdigits = .countleadingdigits!(s, indx+1); 
    50   else static if (!isdigit!(getcharat!(s, indx))) const int countleadingdigits=indx; 
    51   else const int countleadingdigits = .countleadingdigits!(s, indx+1); 
     56    static if (s.length==indx) { 
     57        const int countleadingdigits=indx; 
     58    } else static if (indx==0 && s[indx]=='-')  { 
     59        const int countleadingdigits = .countleadingdigits!(s, indx+1); 
     60    } else static if (!isdigit!( cast(char)s[indx] )) { 
     61        const int countleadingdigits=indx; 
     62    } else { 
     63        const int countleadingdigits = .countleadingdigits!(s, indx+1); 
     64    } 
     65
     66 
     67/******************************* 
     68 *  int sigfigs!(char [] s) 
     69 * 
     70 * Returns the number of significant figures in the decimal number s. 
     71 */ 
     72template sigfigs(char [] s, int p=0) 
     73
     74    static if ( s.length ==p ) { 
     75        const int sigfigs=0; 
     76    } else static if ( s[p]=='.'|| (p==0 && s[p]=='-') ) { 
     77        const int sigfigs = .sigfigs!(s, p+1); 
     78    }else static if ( isdigit!(cast(char)s[p]) ) { 
     79        const int sigfigs = 1 + .sigfigs!(s, p+1); 
     80    } else static if ( s[p]=='e' || s[p]=='E' ) { 
     81        // abort once we reach the exponent 
     82        const int sigfigs=0; 
     83    } else { 
     84        static assert(0); // invalid character in string 
     85    } 
    5286} 
    5387 
     
    67101template fcvt(real x) 
    68102{ 
    69    static if (x<0) const real fcvt = "-" ~ .fcvt!(-x); 
    70    else static if (x==cast(long)x) const char [] fcvt = itoa!(cast(long)x); 
    71    else const char [] fcvt = itoa!(cast(long)x) ~ "." ~ chomp!(afterdec!(x - cast(long)x), '0'); 
     103    static if (x<0) { 
     104        const real fcvt = "-" ~ .fcvt!(-x); 
     105    } else static if (x==cast(long)x) { 
     106        const char [] fcvt = itoa!(cast(long)x); 
     107    } else { 
     108        const char [] fcvt = itoa!(cast(long)x) ~ "." ~ chomp!(afterdec!(x - cast(long)x), '0'); 
     109    } 
    72110} 
    73111 
     
    91129 
    92130version(testmeta) { 
    93  import meta.strhacks; 
     131 private import meta.strhacks; 
    94132  
    95133 static assert( streq!(itoa!(5638), "5638")); 
     
    100138 static assert( countleadingdigits!("325827wip")==6); 
    101139 static assert( countleadingdigits!("abc")==0); 
     140 static assert( sigfigs!("1.2500")==5); 
     141 static assert( sigfigs!("-380.0")==4); 
     142 static assert( sigfigs!("0")==1); 
     143 static assert( sigfigs!("-1.20e49")==3); 
    102144} 
  • trunk/meta/strhacks.d

    r89 r98  
    1 /** Workarounds required for DMD 0.141 
     1/** Workarounds required for DMD 0.142 
    22 * 
    33 * Most of these are only required when they are used as a template value parameter. 
     
    88{ 
    99  const int strlen = str.length; 
    10 } 
    11  
    12 ///  = str[from..to] 
    13 template slice(char [] str, int from, int to) 
    14 { 
    15   const char [] slice = str[from..to]; 
    16 } 
    17  
    18 // = str[n] 
    19 template getcharat(char [] str, int n) 
    20 { 
    21   const char getcharat = str[n]; 
    22 } 
    23  
    24 /// = str[from..$] 
    25 template sliceheadoff(char [] str, int from) 
    26 { 
    27   const char [] sliceheadoff = str[from..str.length]; 
    28 } 
    29  
    30 template slicetailoff(char [] str, int charstochopoff) 
    31 { 
    32   const char [] slicetailoff = str[0..str.length-charstochopoff]; 
    3310} 
    3411 
     
    4421  else static if (str1[0]!=str2[0]) const bool streq=false; 
    4522  else static if (str1.length==1) const bool streq=true; 
    46   else const bool streq = .streq!(slice!(str1, 1, strlen!(str1)), slice!(str2, 1, strlen!(str2))); 
     23  else const bool streq = .streq!(str1[1..(str1.length)], str2[1..(str2.length)]); 
    4724} 
    4825 
     
    7249 static assert(!streq!("abc", "axc") ); 
    7350 static assert(!streq!("abc", "abcd") ); 
    74  static assert(streq!(sliceheadoff!("abcdefg", 3), "defg")); 
     51// static assert(streq!("abcdef", "abc" ~ "def")); // this crashes DMD 0.142 
     52 static assert(streq!("abcdef", concat!("abc", "def"))); 
    7553} 
     54 
     55//----------------------------------------------------------------- 
     56// Workarounds required for DMD 0.141, fixed for DMD 0.142 
     57 
     58///  = str[from..to] 
     59template slice(char [] str, int from, int to) 
     60{ 
     61  const char [] slice = str[from..to]; 
     62} 
     63 
     64/// = str[from..$] 
     65template sliceheadoff(char [] str, int from) 
     66{ 
     67  const char [] sliceheadoff = str[from..str.length]; 
     68} 
     69 
     70template slicetailoff(char [] str, int charstochopoff) 
     71{ 
     72  const char [] slicetailoff = str[0..str.length-charstochopoff]; 
     73} 
     74 
     75// Actually this is still buggy in DMD 0.142, you need to cast(char). 
     76// = str[n] 
     77template getcharat(char [] str, int n) 
     78{ 
     79  const char getcharat = str[n]; 
     80} 
     81 
     82//----------------------------------------------------------------- 
  • trunk/meta/string.d

    r88 r98  
    88{ 
    99  static if (str.length==0) const char[] chomp=str; 
    10   else static if (str[strlen!(str)-1]==delimiter)  
    11      const char [] chomp = .chomp!( slicetailoff!(str, 1), delimiter); 
     10  else static if (str[str.length - 1]==delimiter)  
     11     const char [] chomp = .chomp!( str[0..(str.length-1)], delimiter); 
    1212  else const char [] chomp = str; 
    1313} 
  • trunk/test/linktest1.d

    r94 r98  
    1313    - tests those exported handles 
    1414*/ 
     15 
     16private import test.testclassinterface; 
     17 
     18template getCtorName(char [] fullclassname) 
     19{ 
     20 const char [] getCtorName = "_D" ~ mangleSymbolName!(fullclassname)  
     21    ~ mangleSymbolName!("_ctor") ~ "FZC" ~ mangleSymbolName!(fullclassname); 
     22} 
     23 
     24template getCtorName(char [] fullclassname, P1) 
     25{ 
     26 const char [] getCtorName = "_D" ~ mangleSymbolName!(fullclassname)  
     27    ~ mangleSymbolName!("_ctor") ~ "F" ~P1.mangleof ~ "ZC" ~ mangleSymbolName!(fullclassname); 
     28} 
     29 
    1530void main(){ 
    1631    Stdout.println("Starting."); 
     
    2944    Stdout.println("add: 42+69 = %d",addFun(42,69)); 
    3045    helloWorld(); 
     46 
     47    // Create a class using two different constructors. We need to specify 
     48    // the interface we'll be using (in this case, ITestClass). 
     49    
     50    // Constructor with no parameters 
     51    auto newTestClass = testLibrary.getCtor!(ITestClass, "test.testmodule.TestClass")(); 
     52    auto a = newTestClass();   
     53 
     54    // Constructor with one parameter 
     55    auto newTestClass1 = testLibrary.getCtor!(ITestClass, "test.testmodule.TestClass", int)(); 
     56    auto b = newTestClass1(31415); 
     57 
     58    // Call a member function of the interface 
     59    a.callable(); 
     60    b.callable(); 
    3161     
    3262    Stdout.println("Done."); 
  • trunk/test/testmodule.d

    r66 r98  
    2626 
    2727private import std.stdio; 
     28import test.testclassinterface; 
    2829 
    29 class TestClass{ 
     30 
     31class TestClass : ITestClass { 
    3032    uint a; 
    3133     
    3234    public this(){ 
    3335        a = 1; 
    34         printf("TestClass created\n"); 
     36        printf("TestClass created with no parameters\n"); 
    3537        test(); 
     38    } 
     39    public this(int w) 
     40    { 
     41      a=w; 
     42      printf("TestClass created with parameter %d\n", w); 
     43      test(); 
     44       
     45    } 
     46    public void callable() { 
     47      writefln("In externally callable function, A=", a); 
    3648    } 
    3749     
     
    4153     
    4254    static this(){ 
    43         writefln("TestClass initalized"); 
     55        writefln("TestClass initialized"); 
    4456    } 
    4557}