יצירה וטעינה של ספרייה משותפת בגו

גו היא שפת תכנות מהודרת, אשר יוצרת קבצי ריצה טבעיים של מערכת ההפעלה. מאז גרסה 1.5, נכנסה האפשרות ליצור ספרייה משותפת דינמית (DSO). בגרסה 1.5, התמיכה הייתה ניסיונית, ובגרסה של 1.6, התמיכה נכנסה כתמיכה רשמית של המהדר.

מה זו בעצם ספרייה משותפת?
בקצרה, על רגל אחת, ספרייה משותפת זהו קובץ "ריצה" (למשל בפורמט PE בווינדוז או ELF ביוניקס), אשר אינו מחזיק בחלק ריצה כפרוסס (לרוב נקרא main).
לקובץ הריצה יש רשימה של פונקציות אשר "מיוצאות", כלומר הכתובות שלהם נגישות כלפי חוץ כאשר רוצים להשתמש באותן הפונקציות.
השמות של אותן הפונקציות נקראות symbols והגישה אליהן מתרחשת על ידי כתובות זיכרון.
במידה ופרוסס מסויים מקשר אליהן בצורה סטטית, כלומר בזמן הידור, יודעים את המיקום שלו ביחס לשאר הפונקציות של הפרוסס, כאילו היה חלק מהפרוסס עצמו.
כאשר הטעינה מתבצעת בזמן ריצה, יש אתחול זיכרון דינאמי אשר מחזיק את הכתובת.

כיצד יוצרים ספרייה משותפת בגו?
הרעיון של גו הוא ליצור ב main את הפונקציות שצריכים, ואלו אשר רוצים לייצא, מקבלים הערה אשר אומרת שהם export. עכשיו, וזה חשוב (ואני לא ראיתי את זה בתיעוד, אבל אולי רק פספסתי את זה) המילה export חייבת להיות מיד אחרי ההערה. אם יש רווח, אז זה יראה כאילו מדובר בערה רגילה, ולא בהוראה למהדר.

הדגמה לספרייה:

לאחר כתיבת הקוד, צריך להגיד לגו איך לבנות את הקובץ, ולשם כך יש להשתמש באפשרות הנקראת ‎-buildmode כאשר האפשרות אשר עוברת אליו היא c-shared. אופציה זו אומרת כי לא רק שמדובר בספרייה משותפת, אלא שה ABI יהיה תואם לC.

בשביל שתוכנות מבוססות C או ++C יוכלו לטעון את הספרייה, יש להריץ גם את הפקודה go tool cgo.
הפקודה יוצרת למעשה קובץ header שמכיל הגדרות C לסוגי הנתונים של גו, וכן גם את הפונקציות אשר ייצאו.

כיצד טועניפ ספרייה משותפת בגו?
המהדר של גו, יודע להריץ מקשר (linker) וכן מהדר של c על מנת לבנות קוד שיודע לדבר עם c.

לשם כך, צריך לתת למהדר הוראות בקוד מה בדיוק אנו מעוניינים לעשות. ההוראות, יהיו בתוך הערות, כולל אילו headerים של C לטעון.
חשוב מאוד: יש להצמיד את import "C"‎ בשורה הבאה אחרי ההערה האחרונה המדברת על הוראות לC. אחרת, גו לא ידע מה אנו רוצים ממנו כל כך.

ועכשיו בעיה – ההגדרות אשר נוצרו בפקודה של go tool cgo, יצרו טיפוסי נתונים אשר כבר קיימים בגו, במידה ויהיה ניסיון לטעון את קובץ ה header, הטעינה תיכשל בהודעה כי הטיפוסים כבר הוכרזו בעבר.

בשביל לפתור את הבעיה ניתן ליצור header אשר מכיל רק את הפונקציות הרצויות, או להכריז על הפונקציות בתוך ההערכות של cgo. את האפשרות האחרונה לא ניסיתי, וזו רק השערה.

חשוב לדעת:
גו הינה שפה המכילה גם green threads וגם garbage collection. בנוסף לזה, יש לה יכולות מאוד חזקות להשפיע על ביצוע reflection לטיפוס מסוג interface{}‎. כל היכולות האלו מסייעות בפיתוח, אבל הן מאוד יקרות.

המחיר שלהם הוא בכך שהם מהודרות ישירות לספרייה המשותפת וכן גם לקובץ הריצה.

 

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s