Dem Dennis sein Blogdingen da...
von
Dennis Wronka
am 22.03.09 um 14:24 (1753 Hits)
Wie ich ja bereits berichtet habe befasse ich mich zur Zeit mit C#.
Heute kam dann mal die Frage auf wie denn Libraries die eigentlich fuer C/C++ sind in C# genutzt werden. Wie bei GTK#, welches ja auf GTK aufsetzt.
Hab also gesucht, und gefunden habe ich SWIG - Simplified Wrapper and Interpreter Generator.
Bekannt war mir Swig bereits durch meine Arbeit an EasyLFS. Jedoch nur als Abhaengigkeit fuer irgendeines der SELinux-Pakete.
Entsprechend hab ich also heute mal was genauer auf Swig geschaut und etwas herumgespielt.
Kurz erklaert: Mit Swig nimmt man eine Library, am besten als Source, und legt eine Interface-Beschreibung an.
Diese jagt man durch Swig und kompiliert die Library in beiden Sprachen.
Es geht aber auch mit fertig kompilierten Libraries. Man muss halt nur einen Weg haben die Schnittstellen beschreiben zu koennen.
Hier mal mein kleines Script "sharpify.sh", welches ich dafuer gebastelt habe:
sharpify.sh:
Code bash:
1
2
3
4
5
6
| #!/bin/sh
swig -csharp ${1}.i
gcc -c -fpic ${2} ${1}.c ${1}_wrap.c
gcc -shared ${2} ${1}.o ${1}_wrap.o -o lib${1}.so
gmcs -target:library ${1}.cs ${1}PINVOKE.cs
rm ${1}{,_wrap}.o ${1}_wrap.c ${1}{,PINVOKE}.cs |
Zum Test hab ich in C eine kleine Library geschrieben die wiederum auf der LibClamAV aufsetzt und diese dann mittels Swig nach C# portiert.
Dazu sei natuerlich noch gesagt dass Swig sich nicht auf C# als Ziel-Sprache beschraenkt.
Moegliche Ziele sind, unter anderem, PHP 4 und 5, TCL, Java oder Python.
Hier mal der von mir erstellte C-Code, zum Teil basierend auf einem aelteren C-Projekt wo ich mal mit der LibClamAV gearbeitet habe.
ClamScan.c:
Code c:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| #include <stdio.h>
#include <clamav.h>
struct cl_node *node;
const char *virname;
int ScanRet;
char *DbDir(void)
{
return cl_retdbdir();
}
int LoadDb(char *DbPath)
{
int ret;
unsigned int signo;
ret=cl_loaddbdir(DbPath,&node,&signo);
if (ret)
{
return 0;
}
ret=cl_build(node);
if (ret)
{
return 0;
}
return signo;
}
int ScanFile(char *FilePath)
{
struct cl_limits limits;
ScanRet=cl_scanfile(FilePath,&virname,NULL,node,&limits,CL_SCAN_STDOPT | CL_SCAN_BLOCKMAX);
if (ScanRet==CL_VIRUS)
{
return 1;
}
else if (ScanRet==CL_CLEAN)
{
return 0;
}
else
{
return -1;
}
}
const char *GetVirus(void)
{
return virname;
}
const char *GetError(void)
{
return cl_strerror(ScanRet);
} |
Dazu dann die folgende Interface-Beschreibung:
ClamScan.i:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| %module ClamScan
%{
extern char *DbDir(void);
extern int LoadDb(char *DbPath);
extern int ScanFile(char *FilePath);
extern const char *GetVirus(void);
extern const char *GetError(void);
%}
extern char *DbDir(void);
extern int LoadDb(char *DbPath);
extern int ScanFile(char *FilePath);
extern const char *GetVirus(void);
extern const char *GetError(void); |
Mit dem Shell-Script oben hab ich dann sowohl die Shared Library LibClamScan.so als auch die .NET-Assembly ClamScan.dll erstellt.
Hier nun das C#-Programm in dem ich meine gestutzte C#-Version der LibClamAV teste.
Code csharp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| using System;
namespace ClamTest
{
class MainClass
{
public static string Scan(string FilePath)
{
int ScanRet=ClamScan.ScanFile(FilePath);
switch (ScanRet)
{
case 1:
return ClamScan.GetVirus();
case 0:
return "Clean";
case -1:
return ClamScan.GetError();
}
return "";
}
public static void Main(string[] args)
{
ClamScan.LoadDb(ClamScan.DbDir());
Console.WriteLine(Scan("/home/dennis/sharpify.sh"));
Console.WriteLine(Scan("/home/dennis/doll.com"));
Console.WriteLine(Scan("/home/dennis/doll.exe"));
}
}
} |
Die drei Dateien die ich im Test scanne sind zum einen das oben gezeigte Shell-Script, gefolgt von einem Virus der mal den Weg in meine Mailbox gefunden hat, und anschliessend eine nicht-existente Datei.
Das funktioniert nun alles soweit ganz gut, und war auch recht einfach. Mal davon abgesehen dass ich hier erst eine eigene Library basierend auf LibClamAV geschrieben habe weil der Weg direkt ueber LibClamAV nicht erfolgreich war. Dieses Problem schiebe ich aber auf meine eingeschraenkten Faehigkeiten in C und bei der Erstellung der Interface-Beschreibung als auf Swig oder C#.