Παρασκευή 3 Ιουνίου 2016

Δημιουργία και Εκτέλεση C ρουτινών από τη Μ2000


Στην Έκδοση 10 στο αρχείο info υπάρχει ο κώδικας ανανεωμένος με υποστήριξη για ζήτηση άδειας για την εγγραφή στο   C: σε Windows 10. (εκτελεί το cmd σε elevated, για διαχειριστές, αφού πάρει την άδεια από το χρήστη). Αν επιλέξουμε άλλο φάκελο μέσα στον C: πχ C:\Test δεν έχουμε θέμα.

Το παρακάτω πρόγραμμα το γράφουμε σε ένα αρχείο gsb. Μπορούμε από τη Μ2000 να γράψουμε:
Σ "cdll.gsb"
(όταν το όνομα αρχείου είναι με εισαγωγικά στη Συγγραφή ή Σ  ή Edit τότε διορθώνουμε αρχείο στο δίσκο, δηλαδή με την έξοδο από τον διορθωτή, το αρχείο θα σωθεί, και δεν θα υπάρχει στην μνήμη)
μετά φορτώνουμε με αυτό: (Φόρτωσε ή Load)
Φόρτωσε cdll

και με A (λατινικό) ξεκινάει!

Προϋπόθεση για να λειτουργήσει είναι να υπάρχει ο gcc ο compiler της C  (MinGW)
Αυτόν χρειαζόμαστε:
gcc compiler

(γενικά μετά την εγκατάσταση από τον Installer θα χρειαστεί να πάμε στις ιδιότητες του υπολογιστή και "για προχωρημένους" να βρούμε το κουμπί "environment variables" και στο Path προσθέτουμε το που βρίσκεται ο gcc.exe - θα μπορούσαμε να βάλουμε το μονοπάτι απευθείας στις DOS εντολές του προγράμματος εδώ. Το μονοπάτι το προσθέτουμε βάζοντας το ερωτηματικό ; και μετά το μονοπάτι πχ C:\MinGW\bin)

Ο περισσότερος κώδικας του προγράμματος είναι για να φορμάρουμε την εξαγωγή στην οθόνη,

Με λίγα λόγια:
Φτιάχνουμε ένα dll με τη C με δυο συναρτήσεις. Η μια παίρνει έναν πίνακα Long τον οποίο τον φτιάχνουμε με Buffer (Διάρθρωση) και τον δίνουμε με δείκτη. Το dll έχει φορτωθεί και η κλήση στη συνάρτηση μας γεμίζει τον πίνακα. Η δεύτερη συνάρτηση μας επιστρέφει ένα γινόμενο.
Για να αλλάξουμε το πρόγραμμα στη C πρέπει να δηλώσουμε NEW δηλαδή νέο πρόγραμμα για να βγάλει ο διερμηνευτής την βιβλιοθήκη εκτός, οπότε θα την φορτώσει όταν θα ζητηθεί (διαφορετικά θα χρησιμοποιεί την φορτωμένη).
 Αν βγει λάθος από τον compiler, δεν γυρίζει μήνυμα ειδικό αλλά μας ενημερώνει το πρόγραμμα (επειδή δεν θα υπάρχει το object αρχείο)
Έχω δώσει 1000 χιλιοστά του δευτερολέπτου (1 δευτερόλεπτο) για να εκτελεστεί η εντολή DOS. μετά γυρνάει η ροή στο πρόγραμμα. Αν χρειαστεί το αυξάνουμε!

Δεν υπάρχει σύγκριση, στη C έχουμε αποτέλεσμα σε dt...


Module A {\\ empty the stack
\\ clear values
Refresh 30
Flush : Clear
Fkey 8, {Edit TestMe}
Fkey 9, {Edit c()}
Fkey 10, {Edit a}
Fkey 4, {Flush : TestMe 10000}
Fkey 5, {Save Command$ : Push Command$: New : Cls,0 : Load Letter$ : A}
Clear
Pen #A7CC99
Cursor 0,0
Gradient #738493,#434453
Double
Mark : Print $(4),@(1)," Make a dll and run it - Using gcc from M2000 Interperter"
Normal
      Data "F4","Run 10000","F5","Unload Lib - Compile - Load Lib - Run", "Ctrl+A","Save Program"
      Data "F8","Edit Test M2000 code","F9","Edit C code","F10","Edit Main code"
      c=9
      For i=1 to 3 { Keys(c,0,"-  ") : c++}
      Cursor 0,row-3
      For i=1 to 3 { Keys(c, width/2, "-  ") : c++}
      there=row
Cls #636473, there
\\ Scroll Split there+3
Cls #434453, there+3
\\ a  c program is written in C()
A$= &C()
A$=mid$(A$,2,len(A$)-2)
F=1

Dos "del  c:\adll*.*", 1000;
\\ alt "+" "2" "7" "1" "3" we get ✓
\\ M2000 has unicode internal custom editor
keys(14, 0,"", "✓","Old files Deleted")
open "c:\adll3.c" for output as F
Print #F, A$
close #F
keys(14, 0,"", "✓","Export c:\adll3.c")
dos "cd c:\ && gcc -c -DBUILD_DLL "+"adll3.c", 1000;
if exist("c:\adll3.o") then {
      keys(14, 0,"" ,"✓","Object file complete c:\adll3.o")
      dos "cd c:\ && gcc -shared -o "+"adll3"+".dll "+"adll3"+".o -Wl,--out-implib,libmessage.a", 1000;
} else Print"Error" :exit
if not exist("c:\adll3.dll") then Error "No dll error"
keys(14, 0,"" ,"✓","Linked with gcc c:\adll3.dll")
Push row

Cursor 0,there
\\ Results
dir c:\
Pen 15 {
      keys(14, 0,"" ,"Directory", Dir$)
      menu \\ clear internal menu list
      \\ ! sort by name, + not display just feed menu list
      files ! + "adll3.*"
      If menuitems=0 then break
      For i=1 to menuitems
      cursor 0,row+(i mod 2 =0)
      keys(14, 0-(width/2)*(i mod 2 =0),"" ,str$(i),menu$(i))
      Next i
      if (i mod 2) then print
}
\\ set default directory
Dir User
Cursor 0,Number 'pop row
Print "Perform Test (Y/N):";
Refresh
Clear Yes, No
Repeat {
      Yes=keypress(89)
      No=Keypress(78)
      wait 10
} Until Yes or No
Flush
If Yes then { TestMe } else print "N"
Pen 14

Sub Keys(c, x,pre$)
local t=tab
            Pen c { \\ change Pen only for here, ~(15) change again to white
                  \\ use right justify
                  Print @(x),$(7,6),letter$,
                  italic 1
                        \\ use normal left justify and restore column width
                        Print @(x+6),$(4,t),~(15), pre$+letter$
                  italic 0
            }
            If c>13 then Refresh
End Sub
}
Function C {/* C Code for DLL
*  from an example in M2000
*  Using gcc from http://www.mingw.org/
*  gcc -c -DBUILD_DLL adll3.c
*  gcc -shared -o adll3.dll adll3.o -Wl,--out-implib,libmessage.a
*/
long add2(long a[], long b)
{
      long i, m;
      m=a[0]+2;
      for (i=0;i<b;i++)
                  a[i]=i+m ;
         return 0;
}

long mult(long num1, long num2)
{
   long product;
   product = num1 * num2;
   return product;
}

}
Module TESTME {Pen #A7CC99
max%=200
Read ? max%
\\ we make a buffer
if max%<20 or max%>1000000 then exit
Print Over $(6),"Test for array of"+str$(max%)+" long"
Refresh
Buffer clear alfa as long*max%

\\ Feed unsign 100 to alfa[0]
Return alfa, 0:=100

\\ Now we load lib (lib loaded once)
Declare add2 lib c "c:\adll3.add2" {long c, long d}
Declare mult lib c "c:\adll3.mult" {long c, long d}

\\ We pass alfa(0) as the first long in buffer
Print mult(12,4)

\\ read from memory alfa(0)
\\ and populate array with values
\\ now we get values in buffer (we use as a Peek() this: Eval(<buffer>, index as long))
clear m, m1
Profiler
if add2(alfa(0), Max%) else {
      m=Timecount
      Print eval(alfa,Max%-1), m
}

Dim a(Max%)
Profiler
b=100+2
For i=0 to Max%-1 {
      a(i)=i+b
}
m1=TimeCount

Print a(Max%-1), m1
if m<2 then m=1
Print format$("C is by far the fastest language {0}% from M2000", m1/m*100)

Print Over $(6), "Test 20 Random Items"
Print Under
Equ$=string$("0",log(max%)+1)
Document doc$
Inventory pack
\\ choose one of two methods
If max%<100 then {
\\ use  a populated pack, remove used

for i=0 to max%-1: Append pack, i:=i: next i
            L=Lambda pack -> {
                  if len(pack)=0 then error "empty"

                  k=random(1, len(pack))-1
                  \\ return value (key as value, when no value exist) using k as index
                   =pack(k!)
                                     try {
                    Delete pack, eval$(pack, k)
                    }
                    if error then {
                    cls
                    For i=0 to len(pack)-1
                    print i, pack(i!)
                    next i
                    test
                    a$=key$
                    }
                 
            }
} else {
\\ use an empty pack, store used
      L=Lambda pack, max% -> {
       repeat {
              k=random(0, max%-1)
        } until not exist(pack, k)
        \\ so now k exist, for the next time
        append pack, k
        =k
}
}
For i=1 to 20 {
      k=L()
      doc$= format$("{0}) {1}={2} ({3})",str$(k+1, equ$), eval(alfa, k), a(k), str$(eval(alfa, k)=a(k),{"Not Equal";"Equal";"Not Equal"}))
      if i<20 then {
                  \\ just a new line
                  doc$={
                  }
      }
}
for i=1 to 5 { print}
X=row-5

\\ sorting
Sort Doc$
refresh 1000
For i=1 to 4
      Print @(width*((i-1)/4),X),
      Report 2, doc$, Width/4, 5 Line 5*i-4
Next i
Print
Refresh 30
Pen 14
}

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.