GNU/Linux >> Belajar Linux >  >> Linux

Panduan untuk memahami pustaka perangkat lunak Linux di C

Pustaka perangkat lunak adalah cara lama, mudah, dan masuk akal untuk menggunakan kembali kode. Artikel ini menjelaskan cara membuat pustaka dari awal dan membuatnya tersedia untuk klien. Meskipun dua perpustakaan sampel menargetkan Linux, langkah-langkah untuk membuat, menerbitkan, dan menggunakan perpustakaan ini berlaku untuk sistem mirip Unix lainnya.

Pustaka sampel ditulis dalam C, yang sangat cocok untuk tugas tersebut. Kernel Linux sebagian besar ditulis dalam bahasa C dan sisanya dalam bahasa rakitan. (Hal yang sama berlaku untuk sepupu Windows dan Linux seperti macOS.) Pustaka sistem standar untuk input/output, jaringan, pemrosesan string, matematika, keamanan, penyandian data, dan sebagainya juga ditulis terutama dalam C. Untuk menulis pustaka di C karena itu untuk menulis dalam bahasa asli Linux. Selain itu, C menetapkan tanda kinerja di antara bahasa tingkat tinggi.

Lebih banyak sumber daya Linux

  • Lembar contekan perintah Linux
  • Lembar contekan perintah Linux tingkat lanjut
  • Kursus online gratis:Ikhtisar Teknis RHEL
  • Lembar contekan jaringan Linux
  • Lembar contekan SELinux
  • Lembar contekan perintah umum Linux
  • Apa itu container Linux?
  • Artikel Linux terbaru kami

Ada juga dua klien sampel (satu di C, yang lain di Python) untuk mengakses perpustakaan. Tidak mengherankan bahwa klien C dapat mengakses perpustakaan yang ditulis dalam C, tetapi klien Python menggambarkan bahwa perpustakaan yang ditulis dalam C dapat melayani klien dari bahasa lain.

Perpustakaan statis versus dinamis

Sistem Linux memiliki dua jenis pustaka:

  • Sebuah perpustakaan statis (alias arsip perpustakaan) dimasukkan ke dalam klien yang dikompilasi secara statis (misalnya, satu di C atau Rust) selama fase tautan proses kompilasi. Akibatnya, setiap klien mendapatkan salinan perpustakaannya sendiri. Kelemahan signifikan dari perpustakaan statis muncul ke permukaan jika perpustakaan perlu direvisi (misalnya, untuk memperbaiki bug), karena setiap klien perpustakaan harus ditautkan kembali ke perpustakaan statis. Pustaka dinamis, yang dijelaskan selanjutnya, menghindari kekurangan ini.
  • Sebuah pustaka dinamis (alias bersama) ditandai selama fase tautan program klien yang dikompilasi secara statis, tetapi program klien dan kode perpustakaan tetap tidak terhubung sampai waktu proses—kode perpustakaan tidak dimasukkan ke dalam klien. Saat runtime, pemuat dinamis sistem menghubungkan pustaka bersama dengan klien pelaksana, terlepas dari apakah klien berasal dari bahasa yang dikompilasi secara statis, seperti C, atau bahasa yang dikompilasi secara dinamis, seperti Python. Akibatnya, perpustakaan dinamis dapat diperbarui tanpa mengganggu klien. Terakhir, beberapa klien dapat berbagi satu salinan perpustakaan dinamis.

Secara umum, perpustakaan dinamis lebih disukai daripada perpustakaan statis, meskipun ada biaya dalam kompleksitas dan kinerja. Berikut cara setiap jenis perpustakaan dibuat dan diterbitkan:

  1. Kode sumber untuk pustaka dikompilasi ke dalam satu atau beberapa modul objek, yang merupakan file biner yang dapat disertakan dalam pustaka dan ditautkan ke klien yang dapat dieksekusi.
  2. Modul objek dikemas ke dalam satu file. Untuk pustaka statis, ekstensi standarnya adalah .a untuk "arsip". Untuk perpustakaan dinamis, ekstensinya adalah .so untuk "objek bersama." Dua perpustakaan sampel, yang memiliki fungsi yang sama, diterbitkan sebagai file libprimes.a (statis) dan libshprimes.so (dinamis). Awalan lib digunakan untuk kedua jenis perpustakaan.
  3. File perpustakaan disalin ke direktori standar sehingga program klien, tanpa repot, dapat mengakses perpustakaan. Lokasi khas untuk perpustakaan, baik statis atau dinamis, adalah /usr/lib atau /usr/local/lib; lokasi lain dimungkinkan.

Langkah-langkah terperinci untuk membangun dan menerbitkan setiap jenis perpustakaan akan segera hadir. Namun, pertama-tama, saya akan memperkenalkan fungsi C di dua perpustakaan.

Fungsi perpustakaan sampel

Dua perpustakaan sampel dibangun dari lima fungsi C yang sama, empat di antaranya dapat diakses oleh program klien. Fungsi kelima, yang merupakan utilitas untuk salah satu dari empat lainnya, menunjukkan bagaimana C mendukung penyembunyian informasi. Kode sumber untuk setiap fungsi cukup pendek sehingga fungsi dapat disimpan dalam satu file sumber, meskipun beberapa file sumber (mis., satu per masing-masing dari empat fungsi yang diterbitkan) adalah sebuah opsi.

Fungsi perpustakaan adalah dasar dan berurusan, dalam berbagai cara, dengan bilangan prima. Semua fungsi mengharapkan nilai integer yang tidak ditandatangani (yaitu, non-negatif) sebagai argumen:

  • is_prime fungsi menguji apakah argumen tunggalnya adalah bilangan prima.
  • are_coprimes fungsi memeriksa apakah dua argumennya memiliki pembagi persekutuan terbesar (gcd) dari 1, yang mendefinisikan co-prima.
  • prime_factors function mencantumkan faktor utama argumennya.
  • goldbach function mengharapkan nilai bilangan bulat genap 4 atau lebih, mencantumkan dua bilangan prima mana saja yang dijumlahkan dengan argumen ini; mungkin ada beberapa pasangan penjumlahan. Fungsi ini dinamai dari ahli matematika abad ke-18 Christian Goldbach, yang dugaannya bahwa setiap bilangan bulat genap yang lebih besar dari dua adalah jumlah dari dua bilangan prima tetap menjadi salah satu masalah tertua yang belum terpecahkan dalam teori bilangan.

Fungsi utilitas gcd berada di file perpustakaan yang digunakan, tetapi fungsi ini tidak dapat diakses di luar file yang berisi; karenanya, klien perpustakaan tidak dapat secara langsung memanggil gcd fungsi. Melihat lebih dekat pada fungsi C memperjelas maksudnya.

Selengkapnya tentang fungsi C

Setiap fungsi dalam C memiliki kelas penyimpanan, yang menentukan ruang lingkup fungsi. Untuk fungsi ada dua pilihan:

  • Kelas penyimpanan default untuk fungsi adalah extern , yang memberikan fungsi lingkup global. Program klien dapat memanggil extern fungsi di perpustakaan sampel. Berikut definisi fungsi are_coprimes dengan extern yang eksplisit :
    extern unsigned are_coprimes(unsigned n1, unsigned n2) {
      ...
    }
  • Kelas penyimpanan static membatasi ruang lingkup fungsi ke file di mana fungsi didefinisikan. Di perpustakaan contoh, fungsi utilitas gcd adalah static :
    static unsigned gcd(unsigned n1, unsigned n2) {
      ...
    }

Hanya berfungsi di dalam primes.c file dapat memanggil gcd , dan hanya fungsi are_coprimes melakukannya. Ketika perpustakaan statis dan dinamis dibangun dan diterbitkan, program lain dapat memanggil extern fungsi seperti are_coprimes tapi bukan static fungsi gcd . static kelas penyimpanan dengan demikian menyembunyikan gcd fungsi dari klien perpustakaan dengan membatasi ruang lingkup fungsi ke fungsi perpustakaan lainnya.

Fungsi selain gcd di primes.c file tidak perlu menentukan kelas penyimpanan, yang akan default ke extern . Namun, biasanya di perpustakaan membuat extern eksplisit.

C membedakan antara definisi fungsi dan deklarasi, yang penting untuk perpustakaan. Mari kita mulai dengan definisi. C hanya memiliki fungsi bernama, dan setiap fungsi didefinisikan dengan:

  • Nama yang unik. Tidak ada dua fungsi dalam sebuah program yang memiliki nama yang sama.
  • Daftar argumen, yang mungkin kosong. Argumen diketik.
  • Salah satu jenis nilai yang dikembalikan (mis., int untuk bilangan bulat bertanda 32-bit) atau void jika tidak ada nilai yang dikembalikan.
  • Tubuh yang diapit kurung kurawal. Dalam contoh yang dibuat-buat, tubuh bisa kosong.

Setiap fungsi dalam suatu program harus didefinisikan tepat satu kali.

Berikut adalah definisi lengkap untuk fungsi library are_coprimes :

extern unsigned are_coprimes(unsigned n1, unsigned n2) { /* definition */
  return 1 == gcd(n1, n2); /* greatest common divisor of 1? */
}

Fungsi mengembalikan nilai boolean (baik 0 untuk false atau 1 untuk true), tergantung pada apakah dua argumen bilangan bulat memiliki pembagi persekutuan terbesar 1. Fungsi utilitas gcd menghitung pembagi persekutuan terbesar dari argumen bilangan bulat n1 dan n2 .

Deklarasi fungsi, tidak seperti definisi, tidak memiliki badan:

extern unsigned are_coprimes(unsigned n1, unsigned n2); /* declaration */

Deklarasi diakhiri dengan titik koma setelah daftar argumen; tidak ada kurung kurawal yang menutupi tubuh. Suatu fungsi dapat dideklarasikan beberapa kali dalam suatu program.

Mengapa deklarasi dibutuhkan sama sekali? Di C, fungsi yang dipanggil harus terlihat oleh pemanggilnya. Ada berbagai cara untuk memberikan visibilitas seperti itu, tergantung pada seberapa rewel kompilernya. Salah satu cara yang pasti adalah dengan mendefinisikan fungsi yang dipanggil di atas pemanggilnya ketika keduanya berada di file yang sama:

void f() {...}     /* f is defined before being called */
void g() { f(); }  /* ok */

Definisi fungsi f dapat dipindahkan ke bawah panggilan dari fungsi g jika f dideklarasikan di atas panggilan:

void f();         /* declaration makes f visible to caller */
void g() { f(); } /* ok */
void f() {...}    /* easier to put this above the call from g */

Tetapi bagaimana jika fungsi yang dipanggil berada di file yang berbeda dari pemanggilnya? Bagaimana fungsi yang didefinisikan dalam satu file dibuat terlihat di file lain, mengingat setiap fungsi harus didefinisikan tepat satu kali dalam sebuah program?

Masalah ini berdampak pada perpustakaan, baik statis maupun dinamis. Misalnya, fungsi dalam dua pustaka bilangan prima didefinisikan dalam file sumber primes.c , salinan biner yang ada di setiap perpustakaan; tetapi fungsi yang ditentukan ini harus dapat dilihat oleh klien perpustakaan di C, yang merupakan program terpisah dengan file sumbernya sendiri.

Memberikan visibilitas di seluruh file adalah apa yang dapat dilakukan oleh deklarasi fungsi. Untuk contoh "prima", ada file header bernama primes.h yang mendeklarasikan empat fungsi agar dapat dilihat oleh klien perpustakaan di C:

/** header file primes.h: function declarations **/
extern unsigned is_prime(unsigned);
extern void prime_factors(unsigned);
extern unsigned are_coprimes(unsigned, unsigned);
extern void goldbach(unsigned);

Deklarasi ini berfungsi sebagai antarmuka dengan menentukan sintaks pemanggilan untuk setiap fungsi.

Untuk kenyamanan klien, file teks primes.h dapat disimpan dalam direktori di jalur pencarian kompiler C. Lokasi umum adalah /usr/include dan /usr/local/include . Klien C akan #include file header ini di dekat bagian atas kode sumber klien. (Dengan demikian, file header diimpor ke "kepala" file sumber lain.) File header C juga berfungsi sebagai input ke utilitas (mis., bindgen Rust ) yang memungkinkan klien dalam bahasa lain untuk mengakses pustaka C.

Singkatnya, fungsi perpustakaan didefinisikan tepat satu kali tetapi dideklarasikan di mana pun diperlukan; setiap klien perpustakaan di C membutuhkan deklarasi. File header harus berisi deklarasi fungsi—tetapi bukan definisi fungsi. Jika file header memang berisi definisi, file tersebut mungkin disertakan beberapa kali dalam program C, sehingga melanggar aturan bahwa suatu fungsi harus didefinisikan tepat satu kali dalam program C.

Kode sumber perpustakaan

Di bawah ini adalah kode sumber untuk dua perpustakaan. Kode ini, file header, dan dua contoh klien tersedia di situs web saya.

Fungsi perpustakaan

#include <stdio.h>
#include <math.h>

extern unsigned is_prime(unsigned n) {
  if (n <= 3) return n > 1;                   /* 2 and 3 are prime */
  if (0 == (n % 2) || 0 == (n % 3)) return 0; /* multiples of 2 or 3 aren't */

  /* check that n is not a multiple of other values < n */
  unsigned i;
  for (i = 5; (i * i) <= n; i += 6)
    if (0 == (n % i) || 0 == (n % (i + 2))) return 0; /* not prime */

  return 1; /* a prime other than 2 or 3 */
}

extern void prime_factors(unsigned n) {
  /* list 2s in n's prime factorization */
  while (0 == (n % 2)) {  
    printf("%i ", 2);
    n /= 2;
  }

  /* 2s are done, the divisor is now odd */
  unsigned i;
  for (i = 3; i <= sqrt(n); i += 2) {
    while (0 == (n % i)) {
      printf("%i ", i);
      n /= i;
    }
  }

  /* one more prime factor? */
  if (n > 2) printf("%i", n);
}

/* utility function: greatest common divisor */
static unsigned gcd(unsigned n1, unsigned n2) {
  while (n1 != 0) {
    unsigned n3 = n1;
    n1 = n2 % n1;
    n2 = n3;
  }
  return n2;
}

extern unsigned are_coprimes(unsigned n1, unsigned n2) {
  return 1 == gcd(n1, n2);
}

extern void goldbach(unsigned n) {
  /* input errors */
  if ((n <= 2) || ((n & 0x01) > 0)) {
    printf("Number must be > 2 and even: %i is not.\n", n);
    return;
  }

  /* two simple cases: 4 and 6 */
  if ((4 == n) || (6 == n)) {
    printf("%i = %i + %i\n", n, n / 2, n / 2);
    return;
  }
 
  /* for n >= 8: multiple possibilities for many */
  unsigned i;
  for (i = 3; i < (n / 2); i++) {
    if (is_prime(i) && is_prime(n - i)) {
      printf("%i = %i + %i\n", n, i, n - i);
      /* if one pair is enough, replace this with break */
    }
  }
}

Fungsi-fungsi ini berfungsi sebagai inti untuk pabrik perpustakaan. Kedua perpustakaan berasal dari kode sumber yang sama persis, dan file header primes.h adalah antarmuka C untuk kedua perpustakaan.

Membangun perpustakaan

Langkah-langkah untuk membangun dan menerbitkan perpustakaan statis dan dinamis berbeda dalam beberapa detail. Hanya tiga langkah yang diperlukan untuk perpustakaan statis dan hanya dua langkah lagi untuk perpustakaan dinamis. Langkah-langkah tambahan dalam membangun perpustakaan dinamis mencerminkan fleksibilitas tambahan dari pendekatan dinamis. Mari kita mulai dengan perpustakaan statis.

File sumber perpustakaan primes.c dikompilasi ke dalam modul objek. Berikut perintahnya, dengan tanda persen sebagai prompt sistem (tanda tajam ganda memperkenalkan komentar saya):

% gcc -c primes.c ## step 1 static

Ini menghasilkan file biner primes.o , modul objek. Bendera -c berarti kompilasi saja.

Langkah selanjutnya adalah mengarsipkan modul objek dengan menggunakan ar Linux Linux utilitas:

% ar -cvq libprimes.a primes.o ## step 2 static

Tiga bendera -cvq adalah kependekan dari "create", "verbose", dan "quick append" (jika file baru harus ditambahkan ke arsip). Ingatlah bahwa awalan lib adalah standar, tetapi nama perpustakaannya arbitrer. Tentu saja, nama file untuk perpustakaan harus unik untuk menghindari konflik.

Arsip siap dipublikasikan:

% sudo cp libprimes.a /usr/local/lib ## step 3 static

Pustaka statis sekarang dapat diakses oleh klien, contohnya akan segera hadir. (sudo disertakan untuk memastikan hak akses yang benar untuk menyalin file ke /usr/local/lib .)

Pustaka dinamis juga memerlukan satu atau lebih modul objek untuk pengemasan:

% gcc primes.c -c -fpic ## step 1 dynamic

Bendera yang ditambahkan -fpic mengarahkan compiler untuk menghasilkan kode posisi-independen, yang merupakan modul biner yang tidak perlu dimuat ke lokasi memori tetap. Fleksibilitas seperti itu sangat penting dalam sistem beberapa perpustakaan dinamis. Modul objek yang dihasilkan sedikit lebih besar dari yang dihasilkan untuk perpustakaan statis.

Berikut adalah perintah untuk membuat file library tunggal dari modul objek:

% gcc -shared -Wl,-soname,libshprimes.so -o libshprimes.so.1 primes.o ## step 2 dynamic

Bendera -shared menunjukkan bahwa perpustakaan dibagi (dinamis) daripada statis. -Wl flag memperkenalkan daftar opsi kompiler, yang pertama menetapkan soname perpustakaan dinamis , yang diperlukan. soname pertama-tama tentukan nama logis perpustakaan (libshprimes.so ) dan kemudian, mengikuti -o flag, nama file fisik perpustakaan (libshprimes.so.1 ). Tujuannya adalah menjaga nama logis tetap konstan sambil mengizinkan nama file fisik berubah dengan versi baru. Dalam contoh ini, angka 1 di akhir nama file fisik libshprimes.so.1 mewakili versi pertama dari perpustakaan. Nama file logis dan fisik bisa sama, tetapi praktik terbaiknya adalah memiliki nama yang terpisah. Seorang klien mengakses perpustakaan melalui nama logisnya (dalam hal ini, libshprimes.so ), seperti yang akan saya jelaskan segera.

Langkah selanjutnya adalah membuat perpustakaan bersama mudah diakses oleh klien dengan menyalinnya ke direktori yang sesuai; misalnya, /usr/local/lib again:

% sudo cp libshprimes.so.1 /usr/local/lib ## step 3 dynamic

Tautan simbolis sekarang disiapkan di antara nama logis pustaka bersama (libshprimes.so ) dan nama file fisik lengkapnya (/usr/local/lib/libshprimes.so.1 ). Paling mudah memberikan perintah dengan /usr/local/lib sebagai direktori kerja:

% sudo ln --symbolic libshprimes.so.1 libshprimes.so ## step 4 dynamic

Nama logis libshprimes.so seharusnya tidak berubah, tetapi target tautan simbolik (libshrimes.so.1 ) dapat diperbarui sesuai kebutuhan untuk implementasi perpustakaan baru yang memperbaiki bug, meningkatkan kinerja, dan sebagainya.

Langkah terakhir (tindakan pencegahan) adalah memanggil ldconfig utilitas, yang mengonfigurasi pemuat dinamis sistem. Konfigurasi ini memastikan bahwa pemuat akan menemukan perpustakaan yang baru diterbitkan:

% sudo ldconfig ## step 5 dynamic

Pustaka dinamis sekarang siap untuk klien, termasuk dua contoh berikutnya.

Klien perpustakaan C

Klien sampel C adalah penguji program, yang kode sumbernya dimulai dengan dua #include arahan:

#include <stdio.h>  /* standard input/output functions */
#include <primes.h> /* my library functions */

Tanda kurung siku di sekitar nama file menunjukkan bahwa file header ini dapat ditemukan di jalur pencarian kompilator (dalam kasus primes.h , direktori /usr/local/include ). Tanpa #include , kompiler akan mengeluh tentang deklarasi yang hilang untuk fungsi seperti is_prime dan prime_factors , yang diterbitkan di kedua perpustakaan. Omong-omong, kode sumber untuk program penguji tidak perlu diubah sama sekali untuk menguji masing-masing dari dua pustaka.

Sebaliknya, file sumber untuk perpustakaan (primes.c ) terbuka dengan #include arahan:

#include <stdio.h>
#include <math.h>

File header math.h diperlukan karena fungsi perpustakaan prime_factors memanggil fungsi matematika sqrt di perpustakaan standar libm.so .

Untuk referensi, berikut adalah kode sumber untuk program penguji:

Program penguji

#include <stdio.h>
#include <primes.h>

int main() {
  /* is_prime */
  printf("\nis_prime\n");
  unsigned i, count = 0, n = 1000;
  for (i = 1; i <= n; i++) {
    if (is_prime(i)) {
      count++;
      if (1 == (i % 100)) printf("Sample prime ending in 1: %i\n", i);
    }
  }
  printf("%i primes in range of 1 to a thousand.\n", count);

  /* prime_factors */
  printf("\nprime_factors\n");
  printf("prime factors of 12: ");
  prime_factors(12);
  printf("\n");
 
  printf("prime factors of 13: ");
  prime_factors(13);
  printf("\n");
 
  printf("prime factors of 876,512,779: ");
  prime_factors(876512779);
  printf("\n");

  /* are_coprimes */
  printf("\nare_coprime\n");
  printf("Are %i and %i coprime? %s\n",
         21, 22, are_coprimes(21, 22) ? "yes" : "no");
  printf("Are %i and %i coprime? %s\n",
         21, 24, are_coprimes(21, 24) ? "yes" : "no");

  /* goldbach */
  printf("\ngoldbach\n");
  goldbach(11);    /* error */
  goldbach(4);     /* small one */
  goldbach(6);     /* another */
  for (i = 100; i <= 150; i += 2) goldbach(i);

  return 0;
}

Dalam kompilasi tester.c menjadi executable, bagian yang sulit adalah urutan flag link. Ingat bahwa dua perpustakaan sampel dimulai dengan awalan lib , dan masing-masing memiliki ekstensi biasa:.a untuk perpustakaan statis libprimes.a dan .so untuk perpustakaan dinamis libshprimes.so . Dalam spesifikasi tautan, awalan lib dan ekstensi jatuh. Bendera tautan dimulai dengan -l (huruf kecil L), dan perintah kompilasi mungkin berisi banyak tanda tautan. Berikut adalah perintah kompilasi lengkap untuk program penguji, menggunakan perpustakaan dinamis sebagai contoh:

% gcc -o tester tester.c -lshprimes -lm

Bendera tautan pertama mengidentifikasi perpustakaan libshprimes.so dan tanda tautan kedua mengidentifikasi perpustakaan matematika standar libm.so .

Penautnya malas, yang berarti urutan tanda tautan itu penting. Misalnya, membalik urutan spesifikasi tautan menghasilkan kesalahan waktu kompilasi:

% gcc -o tester tester.c -lm -lshprimes ## danger!

Bendera yang tertaut ke libm.so didahulukan, tetapi tidak ada fungsi dari pustaka ini yang dipanggil secara eksplisit dalam program penguji; karenanya, penaut tidak menautkan ke math.so Perpustakaan. Panggilan ke sqrt fungsi library hanya terjadi di prime_factors fungsi yang sekarang terdapat dalam libshprimes.so Perpustakaan. Kesalahan yang dihasilkan dalam mengkompilasi program penguji adalah:

primes.c: undefined reference to 'sqrt'

Oleh karena itu, urutan tanda tautan harus memberi tahu penaut bahwa sqrt fungsi yang dibutuhkan:

% gcc -o tester tester.c -lshprimes -lm ## -lshprimes 1st

Linker mengambil panggilan ke fungsi perpustakaan sqrt di libshprimes.so perpustakaan dan, oleh karena itu, melakukan tautan yang sesuai ke perpustakaan matematika libm.so . Ada opsi yang lebih rumit untuk penautan yang mendukung urutan bendera tautan; dalam hal ini, bagaimanapun, cara mudah adalah mengatur tanda tautan dengan tepat.

Berikut adalah beberapa keluaran dari menjalankan klien penguji:

is_prime
Sample prime ending in 1: 101
Sample prime ending in 1: 401
...
168 primes in range of 1 to a thousand.

prime_factors
prime factors of 12: 2 2 3
prime factors of 13: 13
prime factors of 876,512,779: 211 4154089

are_coprime
Are 21 and 22 coprime? yes
Are 21 and 24 coprime? no

goldbach
Number must be > 2 and even: 11 is not.
4 = 2 + 2
6 = 3 + 3
...
32 =  3 + 29
32 = 13 + 19
...
100 =  3 + 97
100 = 11 + 89
...

Untuk goldbach fungsi, bahkan nilai genap yang relatif kecil (misalnya, 18) dapat memiliki beberapa pasangan bilangan prima yang menjumlahkannya (dalam hal ini, 5+13 dan 7+11). Beberapa pasangan prima seperti itu adalah salah satu faktor yang memperumit percobaan pembuktian dugaan Goldbach.

Menutup dengan klien Python

Python, tidak seperti C, bukanlah bahasa yang dikompilasi secara statis, yang berarti bahwa klien Python sampel harus mengakses versi dinamis daripada versi statis dari perpustakaan bilangan prima. Untuk melakukannya, Python memiliki berbagai modul (standar dan pihak ketiga) yang mendukung antarmuka fungsi asing (FFI), yang memungkinkan program yang ditulis dalam satu bahasa untuk menjalankan fungsi yang ditulis dalam bahasa lain. Python ctypes adalah FFI standar dan relatif sederhana yang memungkinkan kode Python untuk memanggil fungsi C.

Setiap FFI memiliki tantangan karena bahasa antarmuka tidak mungkin memiliki tipe data yang persis sama. Misalnya, perpustakaan bilangan prima menggunakan tipe C unsigned int , yang tidak dimiliki Python; ctypes FFI memetakan unsigned int ke int Python . Dari keempat extern Fungsi C diterbitkan di perpustakaan bilangan prima, dua berperilaku lebih baik dengan Python dengan ctypes yang eksplisit konfigurasi.

Fungsi C prime_factors dan goldbach memiliki void alih-alih tipe pengembalian, tetapi ctypes secara default menggantikan C void dengan Python int . Saat dipanggil dari kode Python, kedua fungsi C kemudian mengembalikan nilai integer acak (karenanya, tidak berarti) dari tumpukan. Namun, ctypes dapat dikonfigurasi agar fungsi mengembalikan None (Tipe null Python) sebagai gantinya. Berikut konfigurasi untuk prime_factors fungsi:

primes.prime_factors.restype = None

Pernyataan serupa menangani goldbach fungsi.

Sesi interaktif di bawah ini (dalam Python 3) menunjukkan bahwa antarmuka antara klien Python dan perpustakaan prima sangat mudah:

>>> from ctypes import cdll

>>> primes = cdll.LoadLibrary("libshprimes.so") ## logical name

>>> primes.is_prime(13)
1
>>> primes.is_prime(12)
0

>>> primes.are_coprimes(8, 24)
0
>>> primes.are_coprimes(8, 25)
1

>>> primes.prime_factors.restype = None
>>> primes.goldbach.restype = None

>>> primes.prime_factors(72)
2 2 2 3 3

>>> primes.goldbach(32)
32 = 3 + 29
32 = 13 + 19

Fungsi di perpustakaan bilangan prima hanya menggunakan tipe data sederhana, unsigned int . Jika pustaka C ini menggunakan tipe rumit seperti struktur, dan jika pointer ke struktur diteruskan ke dan dikembalikan dari fungsi pustaka, maka FFI lebih kuat daripada ctypes mungkin lebih baik untuk antarmuka yang mulus antara Python dan C. Meskipun demikian, ctypes contoh menunjukkan bahwa klien Python dapat menggunakan pustaka yang ditulis dalam C. Memang, pustaka NumPy yang populer untuk komputasi ilmiah ditulis dalam C dan kemudian diekspos dalam API Python tingkat tinggi.

Pustaka bilangan prima sederhana dan pustaka NumPy tingkat lanjut menggarisbawahi bahwa C tetap menjadi lingua franca di antara bahasa pemrograman. Hampir setiap bahasa dapat berbicara dengan C—dan, melalui C, ke bahasa lain yang berbicara dengan C. Python berbicara dengan mudah ke C dan, sebagai contoh lain, Java dapat melakukan hal yang sama ketika Project Panama menjadi alternatif untuk Java Native Interface (JNI ).


Linux
  1. Perpustakaan Grafis 3d Linux?

  2. Panduan Pemula untuk Manajemen Perangkat Lunak Linux dengan RPM

  3. Di mana saya meletakkan pustaka pihak ketiga untuk menyiapkan lingkungan pengembangan C++ Linux?

  1. Panduan praktis untuk belajar awk

  2. Gunakan perpustakaan C di Swift di Linux

  3. Belajar mengkompilasi sesuatu dari sumber (di Unix/Linux/OSX)

  1. Memahami systemd saat startup di Linux

  2. Cara Memasang Pustaka Ncurses Di Linux

  3. Memahami Desktop Linux?