Di balik Python Trivia #1 dan #2

Daripada blog ini kembali kosong, mari kita bahas Python Trivia babak pertama dan babak kedua yang saya keluarkan lebih dari satu tahun lalu! Mari kita mulai dari babak pertama.

Berikut ini cuplikan kode yang saya tulis:

class Kantong(object):
    def __init__(self, data=[]):
        self.data = data
    def add_data(self, angka):
        self.data.append(angka)
    def cetak(self):
        print 'Daftar angka:', self.data

Lalu mari kita pakai kelas di atas seperti berikut.

satu = Kantong()
satu.add_data(1)
satu.add_data(2)
satu.cetak()

Apa keluarannya?

Daftar angka: [1, 2]

Data yang kita miliki adalah [1, 2] yang berasal dari 2 pemanggilan add_data() dengan parameter 1 dan 2. Gak ada yg protes kan? 😀

Setelah itu, kita buah sebuah objek lain dari kelas yg sama. Lalu 3 buah data baru dimasukkan dan lalu dicetak.

dua = Kantong()
dua.add_data(3)
dua.add_data(4)
dua.add_data(5)
dua.cetak()

Hasilnya adalah.. jreng jreng jreng..

Daftar angka: [1, 2, 3, 4, 5]

Lho lho lho.. kok ada [1, 2] dan bukan cuma [3, 4, 5] padahal kita cuma memasukkan 3 angka di objek baru ini?

Mengapa begini mengapa begitu?

Kalau kita baca kelas Kandong sekali lagi, fungsi add_data akan memasukkan angka ke variabel self.data. Variabel ini diinisialisasi pada bagian constructor __init__() dan nilai awal yg dimasukkan adalah nilai yang ada dalam variabel data dari parameter si constructor.

Jika parameter pada constructor ini tidak diisi, maka secara default nilai data adalah sebuah list kosong []

...
def __init__(self, data=[]):
...

Objek satu dan dua yang dibuat dari kelas Kantong ini tidak menyertakan parameter saat objek dibuat. Alhasil, nilai [] tadi akan dijadikan nilai awal untuk self.data.

Pertanyaannya adalah kapan nilai [] dibuat? Ternyata nilai ini dibuat hanya satu kali pada saat kelas didefinisikan! Artinya, jika nilai tadi tidak diganti, semua objek yang berasal dari kelas Kantong akan memiliki variabel self.data yang sama! Walau tersebar di banyak objek, tapi variabel tersebut menunjuk ke sebuah list yang sama sehingga jika ada penambahan/pengurangan isi list tersebut, semua objek yang memegang list tersebut akan dapat melihatnya.

Lalu bagaimana?

Jika yang kita maksud dengan tidak memberikan parameter adalah sebuah list baru (dan kosong) akan dibuat, maka kelas di atas bisa diubah menjadi berikut.

class Kantong(object):
    def __init__(self, data=None):
        if data is None:
            self.data = []
        else:
            self.data = data
    ...

Dengan demikian, jika parameter tidak dimasukkan (yang artinya data akan bernilai None), variabel self.data akan diisi dengan sebuah list baru yang berbeda dengan list dari objek lain dari kelas yang sama.

Kesimpulannya, pada cara pertama, nilai self.data secara default akan diisi sebuah list yang dibuat pada saat kelas didefinisikan. Pemanggilan constructor (juga termasuk fungsi) akan menggunakan list yang sama dan efeknya adalah adanya penggunaan data bersama. Sedangkan pada contoh kelas ke dua, nilai self.data dibuat pada saat constructor/fungsi dijalankan sehingga pada setiap eksekusi, list baru dan berbeda akan dibuat dan efeknya tidak akan ada penggunaan data bersama.

Bagaimana dengan trivia babak kedua?

Kasus sama juga terjadi di sini.

a = [1] * 5

Kode di atas dapat dibaca seperti berikut. Buat sebuah list baru yang isinya adalah isi list sekarang yang diulang sebanyak 5 kali. Nilai dari a adalah seperti berikut.

[1, 1, 1, 1, 1]

Jika kita ubah salah satu elemennya..

a[3] = 200

Maka nilai si a akan menjadi..

[1, 1, 1, 200, 1]

Masih oke kan? 😀 Apa yang terjadi jika kita menggunakan dict dan bukan angka 1?

b = [{}] * 5

Nilai si b tentunya akan menjadi seperti berikut.

[{}, {}, {}, {}, {}]

Bagimana jika salah dict diubah isinya?

b[0]['a'] = 100

Baris kode di atas artinya ambil elemen nomor 0 dari b (yaitu sebuah dict), lalu kita set kunci 'a' supaya bernilai 100. Bagaimana jika kita cetak nilai si b?

[{'a': 100}, {'a': 100}, {'a': 100}, {'a': 100}, {'a': 100}]

Sesuatu yang (mungkin) tidak diharapkan terjadi lagi 😀 Lagi-lagi hal ini terjadi karena sebenarnya 5 buah dict yang ada di dalam b sebenarnya adalah dict yang sama namun dimasukkan sebanyak 5 kali di dalam list b.

Mudah2an jelas 😀

Mainan baru

… namanya Augmented Reality.

Khusus tuk yg satu ini, saya akan menuliskan perjalanan saya di lapak sebelah: arfriends.net. Situs tersebut adalah sebuah forum yang diharapkan akan menjadi tempat bertukar pikiran, berbagi ilmu, berbagi karya, dsb mengenai Augmented Reality di Indonesia.

Tulisan pertama saya: Instalasi FlashDevelop 😀

Sebelum mulai bikin ini itu, mari kita persiapkan lingkungan kerja 😀 Nah FlashDevelop ceritanya menjadi IDE pilihan karena gratis (dan bebas!). Wah kok Flash? xD Sayangnya Flash saat ini masih menjadi satu platform yang bisa meraih 99% pengguna internet melalui komputer. HTML5 dan kawan2 memang menjanjikan, namun sepertinya masih belum tuk sekarang 🙂

Distributed Version Control System

Wah udah lama saya ngga mengisi blog ini. Saya akan awali lagi mengisi blog ini dengan cerita sedikit mengenai pengalaman saya menggunakan distributed version control system alias DVCS.

Dari sekian DVCS yang ada, saya cuma pernah memakai Bazaar, Git, dan terakhir Mercurial. Saya bisa dibilang sudah meninggalkan Bazaar, yang saya kenal sambil mengembangkan BlankOn, setelah saya mengenal Git. Sejak sekitar dua tahun lalu, saya mencoba menggunakan Mercurial. Sebelum saya menggunakan Bazaar, saya biasanya menggunakan Subversion.

Yang sekarang bisa saya simpulkan mengenai pengalaman saya menggunakan ketiga DVCS ini adalah seperti berikut.

  • Perpindahan dari Subversion ke Bazaar tidak terlalu sulit bagi saya. Saat itu saya hanya perlu tahu konsep repositori lokal, yang secara praktis berarti harus memahami bahwa commit itu hanya akan menyimpan perubahan ke repositori lokal dan push itu dibutuhkan agar perubahan dikirim ke repositori bersama.
  • Saya juga belajar bahwa repositori lokal ini dapat disalin ke direktori lain dan secara otomatis kita akan memiliki sebuah cabang repositori baru.
  • Saat mencoba2 Git, saya menemukan sebuah konsep baru yaitu staging area. Operasi commit pada Git itu hanya akan menyimpan perubahan yang sudah dimasukkan ke dalam staging area. Karena saya masih baru menggunakan Git, perintah git commit -a, yang berarti add dan commit sekaligus, adalah perintah yang saya pakai untuk melakukan commit.
  • Setelah beberapa waktu, saya menemukan operasi commit secara interaktif dengan git commit -i. Saya bisa memilih dulu berkas mana yg ingin saya commit dan mana yg tidak.
  • Selain commit secara interaktif, Git juga memiliki operasi untuk memasukkan berkas ke staging area secara parsial, yang artinya juga kita bisa melakukan commit secara parsial, dengan perintah git add -p. Kita akan dihadapkan dengan pertanyaan bertubi-tubi mengenai setiap perubahan yang kita buat: ingin dimasukkan ke staging area atau tidak.
  • Semakin sering saya menggunakan git add -p semakin paham pula saya apa kegunaan dari staging area dan mengapa ini adalah fitur Git yang sangat powerful yang membedakan Git dengan yang lain
  • Selain ini, saya juga tau bahwa cabang di Git dapat berada di dalam satu buah repositori lokal (alias direktori) yang sama.
  • Setelah saya terbiasa dengan commit parsial, saya mencoba menggunakan Mercurial. Operasi pertama yang saya cari: commit parsial dan pembuatan cabang.
  • Mercurial tidak memiliki staging area sehingga operasi commit akan menyimpan semua perubahan yang dibuat. Sama dengan operasi commit di Bazaar dan bahkan Subversion.
  • Ada pengaya (extension) Mercurial yang dapat membuat kita melakukan commit secara selektif, yaitu Record Extension. Namun walau begitu, ini masih kalah canggih dibanding punyanya Git dalam urusan memilah-milah perubahan.
  • Mercurial memiliki tiga jenis percabangan: cabang dengan nama alias named branch, cabang tanpa nama alias anonymous/unnamed branch, dan bookmark.
  • Cabang dengan nama di Mercurial bersifat permanen: nama cabang akan selalu dibawa ke mana-mana termasuk saat perubahan dikirim ke repositori lain (push).
  • Bookmark adalah jenis cabang di Mercurial yang mirip dengan percabangan di Git.

Kesimpulan lain: Git dapat itu mengubah pikiran dan cara pandang Anda mengenai bagaimana cara menggunakan version control system. Setelah Anda paham mengenai penggunaan Git, maka menggunakan (D)VCS lain itu bisa bikin stres 😛 *kisah nyata*

Ngoprek Microsoft Surface

Yang udah berhasil dilakukan disalahgunakan:

  • Boot ke USB CD/DVD. Password BIOS memang tidak dikasih, tapi ternyata kita bisa minta ke Customer Support Microsoft.

  • Windows 7 dan 8 preview dapat terpasang dengan baik

  • Ubuntu dan BlankOn juga bisa dijalankan (walau tidak nyoba memasangnya). Skrinsut:

  • Microsoft Surface 1.0 SDK (bukan versi Workstation Edition) ternyata sudah tersedia di partisi bawaan (Windows Vista). Awalnya saya kira Microsoft ngga ngasih installer apa2.

  • SDK tadi aslinya hanya bisa dipasang di Windows Vista Business 32bit yg dibawa oleh Microsoft Surface. Namun dengan sedikit utak-atik, SDK ini juga bisa dipasang di atas Windows 7, termasuk yg 64 bit. Seharusnya bisa juga dipasang di atas Windows 8 Preview, namun saya masih gagal memasangnya.

  • MultiTouchVista bisa dipakai untuk membuat windows 7 touch events. Sumber event bisa macem2 termasuk TUIO, multiple mouse, dan juga Surface Input! Saya belum berhasil melakukan kompilasi MultiTouchVista terbaru yg sudah berisi adapter Surface Input. Akhirnya terpaksa menggunakan TUIO dg didampingi konverter Surface Input ke TUIO.

  • Kalau touch events dari Surface Input sudah sampai ke Windows 7, maka kita udah bisa “megang2” si windows 7. IE sudah mendukung scroll dg menggeser halaman (bukan pada scroll bar) sedangkan Firefox 7 dan Chrome 13 (atau 14?) belum.

Sekian.

Port forwarding dg NAT

Ceritanya saya punya mesin, katakanlah bernama C, yang cuma bisa diakses dari dalam jaringan lokal. Saya juga punya mesin bernama M yang bisa diakses dari jaringan lokal DAN juga dari internet. Nah, berhubung si C bisa diakses oleh M, tentu saja saya bisa mengakses C dari internet dg menghubungi M terlebih dahulu.

Cara yang biasa saya lakukan adalah dg membuat koneksi ke M melalui SSH. Setelah di dalam M, saya buka lagi koneksi ke C, lagi-lagi melalui SSH. Intinya saya harus menyiapkan koneksi ke M via SSH terlebih dahulu sebelum saya bisa menghubungi si C. Caranya sendiri pernah saya tuliskan sebelumnya: port forwarding dengan SSH atau dengan membuat socks proxy.

Lama-lama saya malas juga membuat koneksi SSH ke M setiap saya ingin menghubungi C. Mengingat saya memiliki akses administrator di mesin M, akhirnya saya mencoba cara lain, yaitu port forwarding dg NAT alias Network Address Translation. Cara kerja NAT akan saya bahas di lain waktu (kalau ingat, kalau lagi gak malas, kalau mau :P) jadi skr lgs ke inti solusinya saja.

Pertama-tama, aktifkan dulu IP forwarding. (oh iya.. perintah2 ini dikerjakan di mesin M)

# echo 1 > /proc/sys/net/ipv4/ip_forward

Pastikan perintah di atas dijalankan oleh root.. atau versi dengan sudo nya adalah seperti berikut.

$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

Kalau IP forwarding sudah diatur, mari kita buat NAT, atau lebih tepatnya DNAT alias Destination NAT berhubung yang akan dibelokkan itu adalah alamat tujuan koneksi.

$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --source 1.2.3.4 --dport 12345 -j DNAT --to 10.20.30.40:22

Saya ingin membuat NAT yg terbatas dari segi alamat sumber. Dalam contoh di atas, hanya koneksi dari alamat 1.2.3.4 yang akan dialihkan. Selain dari itu, koneksi akan berhenti sampai di sini saja. Selain itu hanya koneksi yg nyampe di eth0 dg protokol tcp di port 12345 yang akan dilayani.

Jika ada koneksi yg sesuai, koneksi ini lalu akan dibelokkan ke mesin dg IP 10.20.30.40, yaitu mesin C, pada port 22.

Singkatnya, jika ada mesin dg IP 1.2.3.4 membuat koneksi ke eth0 di mesin M dg protokol tcp dg 12345, maka koneksi akan dibelokkan ke mesin dg IP 10.20.30.40 pada port 22.

Nah kalau sudah begini, saya dari rumah (yg pake IP 1.2.3.4) bisa membuat koneksi ke mesin C melalui si M tanpa harus membuat koneksi SSH dulu ke M.

rumah$ ssh M -p 12345

Perintah SSH di atas akan langsung terhubung dg mesin C walau koneksi ditujukan ke M karena si M akan membelokkan koneksi ke C.

Selain tuk mengakses C dg SSH langsung dari komputer rumah, yg seperti ini saya pakai juga tuk keperluan lain.. misalnya..

Di mesin M ini saya juga punya sebuah instance virtual machine (VM) dengan VirtualBox. Saya mengaktifkan layanan virtual desktop (dengan RDP) di VirtualBox ini berhubung mesin M ini ada entah-di-mana sehingga saya tidak punya akses fisik langsung. Antara VM dengan host-nya (si M) sudah terjalin hubungan baik melalui jaringan host-only di VirtualBox. Kalau saya ingin mengakses si VM maka, seperti tadi, saya harus mengakses M terlebih dahulu. Dengan melakukan port forwarding, saya bisa mengakses si VM dari C scr langsung.

Pesan commit dari berkas

Saya sedang perlu melakukan banyak commit (seperti biasa, dengan git) berbeda dimana saya ingin memasukkan pesan commit dari sebuah berkas. Kalau saya baca manual dari git-commit, sayangnya Git tidak memiliki fasilitas ini. Git hanya mendukung pemasukkan pesan melalui parameter -m yang saya rasa sangat terbatas atau dengan membuat berkas yg dapat dijadikan sebagai template dari pesan commit. Pembuatan berkas template mungkin mendekati apa yg saya inginkan namun tetap saja saya harus berhadapan dengan teks editor lalu harus menyimpan dan menutupnya sebelum Git dapat melakukan commit. Saya menginginkan semuanya dapat berjalan secara otomatis.

Lalu saya ingat kalau pada dasarnya saya bisa mengganti editor yang akan digunakan oleh Git untuk meminta pengguna memasukkan pesan commit. Pada saat melakukan commit, Git akan memanggil sebuah teks editor dan menunggu sampai teks editor itu ditutup. Berkas yang tadi dibuka oleh teks editor akan dibaca oleh Git lalu isinya dijadikan sebagai pesan commit. Mengatahui alur kerja ini, saya jadi berpikir mengapa tidak membuat teks editor “palsu” saja 😀

Teks editor yang digunakan oleh Git dapat diatur, antara lain, dengan mengatur nilai environment variabel EDITOR. Sebagai contoh, jika ingin menggunakan Gedit untuk menulis pesan commit, kita bisa melakukan hal berikut.

$ EDITOR=gedit git commit

Sebuah berkas bernama .git/COMMIT_EDITMSG akan dijadikan parameter saat teks editor tadi dipanggil sehingga berkas tersebut akan secara otomatis dibuka. Setelah teks editor ditutup, isi dari berkas tadi akan dibaca oleh Git dan dijadikan sebagai pesan commit. Kalau saya ingin membuat teks editor palsu, berarti yang saya harus lakukan adalah menulisi berkas yg diberikan oleh Git dengan pesan commit yang saya inginkan.

Sekitar 6 baris kemudian, akhirnya jadi juga sebuah skrip sederhana yang akan menjadi teks editor palsu. Berikut ini kodenya. Wait.. tunggu.. setelah dipikir2 lagi.. aplikasi sejenis itu sudah ada! aplikasi tersebut adalah.. jreng jreng jreng.. cp alias copy! hah?

Begini ceritanya.. saat git commit dipanggil, maka Git akan menjalankan hal berikut.

$EDITOR .git/COMMIT_EDITMSG

Jika nilai EDITOR adalah gedit, maka yang akan dijalankan oleh Git adalah gedit .git/COMMIT_EDITMSG yang akan meminta Gedit untuk membuka berkas .git/COMMIT_EDITMSG. Setelah aplikasi yg disebut di EDITOR dideteksi sudah ditutup, maka Git akan membaca berkas .git/COMMIT_EDITMSG dan menggunakannya (saya udah nulis yg seperti ini berapa kali ya?).

Kalau diteliti lebih lanjut, nilai EDITOR itu juga bisa mengandung parameter lain. Sebagai contoh, Gedit memiliki opsi --new-window yang kalau dipakai, maka berkas yang disebutkan akan dibuka di jendela Gedit baru, bukan sekedar di tab baru dari window yg sudah ada (asumsinya sudah ada window Gedit yg terbuka). Jika Gedit ingin dijalankan dengan opsi ini pada saat melakukan commit, maka yang berikut ini bisa dilakukan.

$ EDITOR="gedit --new-window" git commit

Apakah hal tersebut berlaku untuk opsi (yg dimulai dengan - atau --) apakah bisa parameter lain termasuk nama berkas? Ternyata bisa! Coba saja yg berikut ini.

$ EDITOR="gedit a b c" git commit

Maka selain .git/COMMIT_EDITMSG, berkas a, b, dan c juga akan dibuka oleh Gedit.

Nah, kembali ke cp, bagaimana kita bisa memanfaatkan cp untuk melakukan commit dengan pesan yg dibaca dari sebuah berkas? Jawabannya adalah dengan menjadikan cp sebagai EDITOR dan berkas tadi sebagai parameter pertamanya. Saat commit dipanggil, Git akan memasukkan parameter kedua dan mengeksekusinya. Alhasil, perintah yang dipanggil adalah salin berkas yg disebut ke .git/COMMIT_EDITMSG 😀

$ EDITOR="cp /tmp/berkas-berisi-pesan-commit.txt" git commit

Voila! git commit akan keluar seketika namun commit tetap sudah terjadi. Jika melihat log, isi berkas yg disebut akan menjadi pesan commit.

Lho? kok bisa? bisa karena teks editor akan dibuka oleh Git dengan melakukan perintah berikut.

cp /tmp/berkas-berisi-pesan-commit.txt .git/COMMIT_EDITMSG

Perintah tadi akan jalan sekejap dan Git akan otomatis mendeteksi kalau perintah cp sudah selesai dieksekusi. Isi .git/COMMIT_EDITMSG akan diasumsikan sudah berisi pesan commit sehingga bisa digunakan oleh Git 😀

~

Pertama: Amsterdam West, September 2007 – Juli 2008

Jatah dari kampus tuk para pendatang baru. Gedung apartemen berupa susunan kotak kontainer bercat putih dengan kaca warna-warni. Terletak persis di sebelah kanal dan sebuah kapal pesiar yang disulap jadi asrama mahasiswa xD

Kedua: Amsterdam Oost, September 2008 – April 2010

Ini juga jatah dari kampus yang didapat dengan harap-harap cemas karena jatah yang terbatas. Gedung apartemen tua yang juga dilengkapi dengan fasilitas tikus xD Walau begitu, lokasi sangat dekat dengan kampus dan harganya juga harga mahasiswa.

Ketiga: Diemen Centrum, Agustus 2010 – Juni 2011

Tempat pertama yang didapat dari agen rumah. Gedung lumayan baru, mungkin dari sekitar awal tahun 2000 *sotoy* sehingga semuanya masih bersih dan kinclong. Lokasi ada di daerah kecil bukan Amsterdam yang berada tepat di sebelah Amsterdam. Kalau Amsterdam itu Cirebon, Diemen ini mungkin Kuningan. Walau “di luar kota”, untungnya jarak ke kampus masih deket sekitar 3 km saja 😀

Keempat: Amsterdam Nieuw-West, Mei/Juni 2011 – …

Dari Barat Laut, lalu ke Timur, lalu ke Tenggara agak Utara sedikit, selanjutnya pindah lagi ke daerah Barat. Tempat yg ini belum pernah ditempati jadi belum tau suasananya seperti apa. Dari pengamatan sebentar, lokasi cukup enak karena persis di depan pusat belanja dengan 3 supermarket hohoho.. kantor pemda, rumah sakit, toko kelontong, obat2an/peralatan mandi, toko daging halal, toko kebab sampe resto indonesia juga gak jauh dari rumah. Stasiun kereta dan metro kira2 bisa dicapai dengan 10 menit jalan kaki.

Satu hal yang membedakan tempat ini dengan 3 tempat sebelumnya adalah apartemen ini tidak hadir dengan isinya. *siap2 jadi tukang cat dan pasang lantai*

Komunikasi .NET dan Python melalui COM

Saat ini saya sedang membutuhkan akses ke sebuah pustaka yang hanya tersedia dalam platform Microsoft .NET. Berhubung apa yang saya buat semuanya tertulis dalam bahasa Python, tepatnya CPython, saya perlu mencari cara bagaimana agar saya bisa mengakses pustaka dalam .NET tersebut dari Python. Setelah ngubek sana sini, akhirnya ketemu juga (salah satu) caranya, yaitu melalui Component Object Model alias COM. Singkatnya, COM ini memungkinkan berbagai aplikasi dengan berbagai bahasa untuk berkomunikasi.

Membuat komponen COM dengan C#

Dalam kasus yang saya hadapi, saya perlu mengakses pustaka .NET dari Python. Oleh karena itu saya membutuhkan sebuah komponen COM yang tertulis dalam, misalnya, C# yang dapat mengakses pustaka tersebut. Komponen dalam C# ini lalu saya atur agar bisa diakses melalui COM sehingga pada akhirnya aplikasi Python saya bisa mengakesenya.

Kali ini saya akan mencontohkan cara membuat sebuah kelas dalam C# yang dapat diakses melalui COM. Kelas ini adalah sebuah kelas kalkulator yang berisi fungsi penjumlahan angka. Contoh ini saya adaptasi dari beberapa referensi bagus yang ada di [1,2,3].

Buat sebuah proyek C# baru bernama Matematika dan kemudian buat sebuah sebuah kelas dengan isi seperti berikut.

namespace Matematika {
    public interface IKalkulator {
        int tambah(int a, int b);
    }

    public class Kalkulator : IKalkulator {
        public int tambah(int a, int b) {
            return a + b;
        }
    }
}

Interface adalah bagian penting dalam pembuatan komponen COM karena dalam COM pengaksesan komponen akan mengacu kepada interface yang dibuat.

Untuk keperluan pendaftaran komponen, kita memerlukan sebuah kunci. Buka Visual Studio Command Prompt, pindah ke direktori proyek (direktori dimana kode sumber berada, bukan direktori Solution-nya visual studio) dan jalankan perintah berikut.

sn.exe -k Matematika.snk

Setelah itu, buka berkas AssemblyInfo.cs (ada di bawah Solution -> Matematika -> Properties) dan tambahkan 3 baris berikut.

[assembly: ComVisible(true)]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("Matematika.snk")]

Lakukan kompilasi proyek untuk membuat berkas pustaka Matematika.dll. Berkas pustaka ini akan berada di bawah direktori binRelease yang ada di bawah direktori proyek.

Agar pustaka atau komponen COM ini dapat diakses dari aplikasi lain, kita harus mendaftarkan pustaka ini terlebih dahulu. Untuk ini, kita perlu menggunakan akses sebagai Administrator. Buka Visual Studio Command Prompt lagi namun kali ini sebagai Administrator (Klik kanan di shortcut dan pilih Run as Administrator). Masuk ke direktori tempat pustaka Matematika.dll tadi berada (direktori binRelease di bawah direktori kerja) lalu jalankan perintah pendaftaran berikut.

regasm.exe Matematika.dll /tlb:Matematika.tlb /codebase

Setelah perintah di atas dijalankan, Anda akan mendapatkan pesan kalau pustaka sudah didaftarkan dan juga sebuah berkas baru bernama Matematika.tlb yang berisi deskripsi mengenai seluruh interface dan struktur data yang ada.

Sebelum lanjut ke cara mengakses komponen tadi, buka lagi berkas AssemblyInfo.cs dan dapatkan tanda pengenal aplikasi yang barusan dibuat. Tanda pengenal ini adalah sebuah GUID yang didefinisikan seperti berikut.

[assembly: Guid("9808bb58-40fe-4373-acc3-f577b55a2a99")]

Deretan angka dan huruf di atas, yaitu 9808bb58-40fe-4373-acc3-f577b55a2a9, akan menjadi (salah satu) tanda pengenal yang dibutuhkan saat mengakses komponen COM tadi.

Mengakses COM dari Python

Python tidak menyediakan dukungan terhadap COM secara langsung sehingga kita perlu memasang modul tambahan yang dapat membantu kita untuk mengakses COM. Saya menemukan ada dua modul yang bisa digunakan, yaitu PyWin32 dan comtypes. Dalam petualangan beberapa hari terakhir ini, saya belum berhasil mengakses COM yang saya buat di .NET dengan bantuan PyWin32 namun comtypes dapat melakukannya dengan cukup mudah. Oleh karena itu, saya akan mencontohkan penggunaan comtypes untuk mengakses komponen COM yang tadi dibuat. Berhubung comtypes itu bukan bawaan asli dari Python, unduh dan pasang dulu modul ini dari http://pypi.python.org/pypi/comtypes.

Kalau sudah, buat sebuah berkas matematika.py yang berisi kode berikut.

import comtypes
import comtypes.client as cc

guid = comtypes.GUID("{9808bb58-40fe-4373-acc3-f577b55a2a99}")
cc.GetModule((guid, 1, 0))

from comtypes.gen import Matematika

obj = cc.CreateObject("Matematika.Kalkulator", None, None,
                      Matematika.IKalkulator)

a = 10
b = 200
hasil = obj.tambah(a, b)

print a, '+', b, '=', hasil

Setelah itu, jalankan dengan python.exe

C:tmp>c:Python26python.exe matematika.py
# Generating comtypes.gen._9808BB58_40FE_4373_ACC3_F577B55A2A99_0_1_0
# Generating comtypes.gen._00020430_0000_0000_C000_000000000046_0_2_0
# Generating comtypes.gen.stdole
# Generating comtypes.gen._BED7F4EA_1A96_11D2_8F08_00A0C9A6186D_0_2_0
# Generating comtypes.gen.mscorlib
# Generating comtypes.gen.Matematika
10 + 200 = 210

Dalam eksekusinya, comtypes akan membuat beberapa modul tambahan (yang berfungsi kode penghubung dengan komponen COM) secara otomatis seperti yang diperlihatkan dalam hasil di atas. Modul dan pesan ini hanya akan dibuat satu kali sehingga pada eksekusi selanjutnya pesan di atas tidak akan tampil lagi.

Jika ada perubahan dalam kode C# yang kita buat, selama kita tidak mengubah interface, kita cukup melakukan kompilasi ulang dan pustaka baru akan langsung dipakai. Jika interface berubah, pustaka perlu didaftarkan ulang (dan berkas .tlb-nya juga perlu dibuat ulang) agar perubahan dapat diketahui. Berdasarkan berkas .tlb yang berubah, comtypes akan melakukan pembuatan ulang modul penghubung secara otomatis juga.

Referensi

  1. http://msdn.microsoft.com/en-us/library/aa645738(v=vs.71).aspx
  2. http://support.microsoft.com/kb/828736
  3. http://cppkid.wordpress.com/2009/01/02/how-to-call-a-managed-dll-from-unmanaged-code/