מבוא לתכנות של קבוצת בטא/המדריך המהיר של עופר לשפת ג'וליה/ג'וליה ושפת C

הכנות עריכה

בשביל לקרוא לג'וליה מתוך C נצטרך לדעת איפה ספריית הג'וליה ואיפה הinclude של ג'וליה. ואנחנו עובדים על לינוקס. ככה זה בטא, תתמודדו.

טוב, איך מתקינים ג'וליה בלינוקס? עריכה

מורידים את אחד מקבצי ההתקנה באתר הרשמי של ג'וליה. והנה הסבר באנגלית על איך מתקינים, יום אחד מישהו יכתוב אותו גם בעברית: הסברים על התקנה בלינוקס מהאתר הרשמי של ג'וליה.

אז איפה כל הספריות והincludes המופלאים האלו? עריכה

כל הממתקים האלו נמצאים בתיקיה בה התקנתם את ג'וליה.
אם אין לכם מושג איפה זה, אפשר להריץ את הפקודה הזו:

ls -l $(dirname $(which julia))

אם הפקודה הוציאה משהו, זו התיקיה של ג'וליה. אצלי זה הוציא:

/home/foo/julia/julia-1.8.3

כי אני פשוט פתחתי את ג'וליה בתיקיית הבית שלי בלי התקנות. ובהתאם אצלי הlibrary נמצאת ב:

/home/foo/julia/julia-1.8.3/lib/julia.so

והinclude נמצא ב:

/home/foo/julia/julia-1.8.3/include/julia/julia.h

יופי. תזכרו את התיקיה הזאת.

מבשלים את הMakefile עריכה

מה זה Makefile? עריכה

זה קובץ בשם Makefile שכותבים לתוכו הגדרות לקומפיילר. ככה פקודת make יכולה להריץ במקומכם המון פקודות קימפול מסובכות ולחסוך לכם כאב ראש.
לא, זה לא קשור לג'וליה, זה קשור לסביבת העבודה של C. ואין על זה אף מילה בויקיספר C, כי הויקיספר הוא למתחילים, ולכם יש כבר 30 נקודות. אתם כבר לא בקנזס.

ולמה צריך makefile עכשיו? מה היה לנו רע בחיים? עריכה

כי יש הרבה הוראות לקומפיילר, אז Makefile יעזור למסך שלנו להישאר בלי קישקושים.

אוי. כתוב שאין לי gcc או make או משהו אחר עריכה

אז תורידו עם apt-get. קדימה, למדתם על זה במדריך המהיר ללינוקס.

לבשל! עריכה

צרו קובץ בשם Makefile. פתחו אותו בעורך טקסט וכתבו שם את זה (זה קובץ הMakefile אצלי):

CARGS = -fPIC -g
JULIA_DIR = /home/foo/julia/julia-1.8.3
JLARGS = -I$(JULIA_DIR)/include/julia -L$(JULIA_DIR)/lib -Wl,-rpath,$(JULIA_DIR)/lib -ljulia

hello_c.elf: hello.c
        gcc $(CARGS) $< $(JLARGS) -o $@

כמובן, תחליפו את מה שנכנס שם לJULIA_DIR בתיקיית הג'וליה שמצאתם אצלכם.

אז מה כתבנו שם בעצם? (כאן יהיה ניתוח של הקובץ)

לכתוב ג'וליה בC עריכה

בואו נתחיל בקטן: הדפסה של שלום עולם, כתובה בג'וליה, בתוך קובץ C:

#include <julia.h>
JULIA_DEFINE_FAST_TLS

int main()
{
  jl_init();

  jl_eval_string("println(\"Hello world!\")");

  jl_atexit_hook(0);
  return 0;
}


מה זה זה? עריכה

(כאן יבוא הסבר על השורות בקובץ)

זה עובד! עריכה

כן. למעשה ברוב שפות התכנות אינטגרציות כאלו עובדות רק אחרי שאתם עושים במשך שבועות הגדרות, תיקונים, חיפושים באינטרנט אחרי אנשים שנמצאים באותה צרה, ובכי ותחנונים לקומפיילר.
בג'וליה זה פשוט עובד.

מהירות? עריכה

אז מה יותר מהיר, להריץ printf או לתת לג'וליה להדפיס בשבילנו?
תשובה נכונה, השאלה מעליבה לכם את האינטיליגנציה. אבל עד כמה היא מעליבה? בואו נבדוק.
נתזמן את ההרצה של הדפסת ג'וליה (ותודה לחברים בstackoverflow שמסבירים את פתרון התזמון הזה):

#include <time.h>
#include <sys/time.h>
#include <stdint.h>

#include <julia.h>
JULIA_DEFINE_FAST_TLS

uint64_t get_posix_clock_time();

int main()
{
  uint64_t tic = get_posix_clock_time();

  jl_init();

  jl_eval_string("println(sqrt(2.0))");

  jl_atexit_hook(0);

  uint64_t toc = get_posix_clock_time();

  printf("\ntiming: %f[ms] (%d[microsec])\n", (toc - tic)/1000.0, toc - tic);

  return 0;
}

uint64_t get_posix_clock_time()
{
  struct timespec ts;

  if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0) {
    return (uint64_t) (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
  } else {
    return 0;
  }
}

אצלי יצא timing: 229.650000[ms] (229650[microsec]).

ועכשיו נכניס את ג'וליה להערה, ונתזמן את printf (זה אותו קוד, רק שיניתי 4 שורות):

#include <time.h>
#include <sys/time.h>
#include <stdint.h>

#include <julia.h>
JULIA_DEFINE_FAST_TLS

uint64_t get_posix_clock_time();

int main()
{
  uint64_t tic = get_posix_clock_time();

  printf("hello\n");

  #jl_init();

  #jl_eval_string("println(sqrt(2.0))");

  #jl_atexit_hook(0);

  uint64_t toc = get_posix_clock_time();

  printf("\ntiming: %f[ms] (%d[microsec])\n", (toc - tic)/1000.0, toc - tic);

  return 0;
}

uint64_t get_posix_clock_time()
{
  struct timespec ts;

  if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0) {
    return (uint64_t) (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
  } else {
    return 0;
  }
}

יצא לי timing: 0.462000[ms] (462[microsec]).

שזה מעליב באיזה 229 מילישניות. כן, ג'וליה האיטה אותו ב49707%.
מסקנה: אם קוד הג'וליה שלכם לא חוסך 229 מילישניות של זמן ריצה... בעצם, תשכחו מזה. הוא כנראה עדיין חוסך 223 שעות של זמן מתכנת.

הערכים של ג'וליה עריכה

(כאן יהיה טקסט על איך מחזירים ערך מג'וליה לתוך משתנה בC)

רוצי, פונקציה, רוצי עריכה

(כאן יהיה טקסט על איך מריצים פונקציית ג'וליה ישירות מתוך C)

מקורות עריכה

יש פוסט מצויין של אבל סוארז סיקיירה על כל הנושא של אינטגרציה בין ג'וליה לC++ (מנובמבר 2022, מתבסס על גירסה 1.8).