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/