將你的 C 語言程式碼編譯成 .NET

2016-10-20    分類:.NET開發、程式設計開發、首頁精華3人評論發表於2016-10-20

本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

介紹

通常情況下,對於那些使用C語言程式設計並開始用C#/ VB或一些其他的用於.NET的編譯語言程式設計,那麼他們希望或者甚至是需要呼叫我們用C語言編寫的函式程式碼。

每當我在網際網路上鑽研,或說要在編譯器中使用Visual C ++與/clr ,或使用pInvoke來呼叫C語言函式,都有這樣的心情。

所以我在和我的朋友,OrangeC / C ++編譯器的創造者,David交流的時候,我給他出了個主意,那就是為你的編譯器建立一個新的後端來生成CLR程式碼,這樣一來,就沒有生成CLR程式碼的C語言開源編譯器了。

在分離生成x86程式碼的編譯器後端後,新的後端的開發在一些修復和實現之後開始了,我們已經成功取得編譯器SQLite3並使用DLL與C#程式碼一起編譯。

C / C ++編譯器和到MSIL後端的連結

你可以遵循OrangeC / C ++編譯器的開發,或致力於以下連結的專案貢獻:

構建Orangec編譯器和用於MSIL的Orangec

要構建MSIL的Orange C編譯器,你需要下載OrangeC編譯器的完整程式碼,你可以在這裡得到原始碼:

或者

在你下載原始碼後,在C:\orangec解壓所有zip檔案,在解壓所有檔案後,你需要下載MSIL後端

解壓所有檔案到資料夾C:\orangec\src\occ,當出現替代選項的時候,接受替代檔案。

要構建和生成原始碼,必須具備下面其中一個編譯器:

  • MinGW
  • Borland C / C ++ 5.5(我用這個編譯器來構建編譯程式)
  • CLang
  • Visual C / C ++ 10
  • OrangeC 編譯器

在下載和解壓所有檔案後,開啟CMD導航到資料夾C:\orangec\src,type,config.bat,在執行config.bat,type後:

  • omake fullbuild

這將建立所有的orangec編譯器。

構建後,也許你會看到一個關於建立zip檔案的錯誤,但是不要擔心。

好了,現在你已經編譯好了所有的OrangeC / C ++工具鏈,為了構建後端到MSIL,你需要去到資料夾C:\orangec\src\occ\netil,在這個資料夾裡面,type(在系統路徑中具備ILASM 和CSC (C#編譯器)編譯器時必須的):

  1.  omake netlib.lib
  2.  omake

在執行這一命令後,你就有了occil.exe

使用OrangeC編譯器來生成MSIL程式碼

要使用編譯器,你只需下載這篇文章中提供的連結,建立資料夾C:\orangec,解壓該資料夾中的所有zip內容,開啟CMD,然後導航到C:\orangec資料夾,在orangec 資料夾中,type,config.bat後,當執行 config.bat檔案時,一個新的環境變數將在CMD背景下建立,因此編譯器可以定位include資料夾。

*重點* ——在你的路徑中具備ILASM.EXE很有必要,為了做到這一點,你有兩個辦法把 ILASM放到你的路徑中:

  1. 執行VSVARS32.BAT
  2. 在你的CMD中執行以下命令:PATH = C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH%

在構建生成的IL程式碼到EXE / DLL時,在路徑中具備ilasm是有必要,然而我們正在OrangeC中實施oilasm。

建立一個小例子

建立一個名為“float_to_ieee754.c”的C檔案,並把程式碼放到C檔案:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *strrev_t(char *str)
{
    char *p1, *p2;

    if (!str || !*str)
        return str;
    for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
    {
        *p1 ^= *p2;
        *p2 ^= *p1;
        *p1 ^= *p2;
    }
    return str;
}

void floatToBinary(float f, char *str, int numeroDeBits)
{
    int i = 0;
    int strIndex = 0;
    union
    {
        float f;
        unsigned int i;
    }u;
    u.f = f;
    memset(str, '0', numeroDeBits);

    for (i = 0; i < numeroDeBits; i++)
    {
        str[strIndex++] = (u.i & (1 << 0)) ? '1' : '0';
        u.i >>= 1;
    }

      str[strIndex] = '\0';

    str = strrev_t(str);
}

int main()
{
    float input = 0.0;
    const int numeroDeBits = 32;
    char *str = (char*)malloc(sizeof(char) * numeroDeBits);
    printf("Type a float number to convert to binary: ");
    scanf("%f", &input);
    floatToBinary(input, str, numeroDeBits);
    printf("%s\n", str);
    if(str != NULL)
    free(str);     
    return 0;
}

現在,為了構建程式碼,你需要在CMD中鍵入:

occil /NProgram.FloatToBinary /9 float_to_ieee754.c

每個引數的說明:

  • /N<NameSpace>.<Class>
  • /9: C99 mode

在執行此命令後,編譯器將生成指向你的程式碼的IL程式碼和occil呼叫ilasm來生成來自於IL程式碼的EXE / DLL。如果你想看到生成的IL程式碼,只要看看你的C程式碼所在的資料夾,開啟“float_to_ieee754.il”。

生成IL程式碼:

//File float_to_ieee754.il
//Compiler version MSIL Compiler

.corflags 3 // 32-bit
.assembly float_to_ieee754 { }

.assembly extern mscorlib { }

.assembly extern lsmsilcrtl { }

.namespace 'Program' {

.class public explicit ansi sealed 'FloatToBinary' {
.field public static valuetype 'Program.FloatToBinaryøint8[]' 'L_3' at $L_3
.data $L_3 = bytearray (25 73 a 0
)
.field public static valuetype 'Program.FloatToBinaryøint8[]' 'L_2' at $L_2
.data $L_2 = bytearray (25 66 0
)
.field public static valuetype 'Program.FloatToBinaryøint8[]' 'L_1' at $L_1
.data $L_1 = bytearray (54 79 70 65 20 61 20 66
    6c 6f 61 74 20 6e 75 6d
    62 65 72 20 74 6f 20 63
    6f 6e 76 65 72 74 20 74
    6f 20 62 69 6e 61 72 79
    3a 20 0
)
.method public hidebysig static int32 'main'(int32 'argc', void * 'argv')  cil managed
{

// Line 43:    int main()

    .maxstack    3
    .locals(
        [0]        float32 'input/0',
        [1]        void* 'str/1'
    )

L_4:
// Line 45:        float input = 0.0;

    ldloca    'input/0'
    ldc.r4    0.0
    stind.r4
// Line 46:        const int numeroDeBits = 32;

    ldloca    'str/1'
    ldc.i4    32
    conv.u4
    call    void* [lsmsilcrtl]lsmsilcrtl.rtl::malloc(uint32)
    stind.i4
// Line 48:        printf("Type a float number to convert to binary: ");

    ldsflda    valuetype 'Program.FloatToBinaryøint8[]' Program.FloatToBinary::L_1

    call    vararg int32 'printf'(void*, ...)
    pop
// Line 49:        scanf("%f", &input);

    ldsflda    valuetype 'Program.FloatToBinaryøint8[]' Program.FloatToBinary::L_2

    ldloca    'input/0'
    call    vararg int32 'scanf'(void*, ..., void*)
    pop
// Line 50:        floatToBinary(input, str, numeroDeBits);

    ldloc    'input/0'
    ldloc    'str/1'
    ldc.i4    32
    call    void Program.FloatToBinary::'floatToBinary'(float32, void*, int32)
// Line 51:        printf("%s\n", str);

    ldsflda    valuetype 'Program.FloatToBinaryøint8[]' Program.FloatToBinary::L_3

    ldloc    'str/1'
    call    vararg int32 'printf'(void*, ..., void*)
    pop
// Line 52:        if(str != NULL)

    ldloc    'str/1'
    brfalse 'L_7'

// Line 53:        free(str);     

    ldloc    'str/1'
    call    void [lsmsilcrtl]lsmsilcrtl.rtl::free(void*)
L_7:
// Line 54:        return 0;

    ldc.i4    0
// Line 55:    }

L_5:
    ret

}
.method public hidebysig static void* 'strrev_t'(void* 'str' ) cil managed
{
// Line 5:    char *strrev_t(char *str)

    .maxstack    4
    .locals(
        [0]        void* 'p1/0',
        [1]        void* 'p2/1'
    )

L_17:
// Line 7:        char *p1, *p2;

// Line 9:        if (!str || !*str)

    ldarg    'str'
    brfalse 'L_37'

    ldarg    'str'
    ldind.i1
    brtrue 'L_20'

L_37:
// Line 10:            return str;

    ldarg    'str'
    br 'L_18'

L_20:
    ldarg    'str'
    stloc    'p1/0'
    ldarg    'str'
    call    uint32 'strlen'(void*)
    ldarg    'str'
    add
    ldc.i4    1
    sub
    stloc    'p2/1'
    br 'L_26'

L_25:
// Line 12:        {

// Line 13:            *p1 ^= *p2;

    ldloc    'p1/0'
    ldloc    'p1/0'
    ldind.i1
    ldloc    'p2/1'
    ldind.i1
    xor
    stind.i1
// Line 14:            *p2 ^= *p1;

    ldloc    'p2/1'
    ldloc    'p2/1'
    ldind.i1
    ldloc    'p1/0'
    ldind.i1
    xor
    stind.i1
// Line 15:            *p1 ^= *p2;

    ldloc    'p1/0'
    ldloc    'p1/0'
    ldind.i1
    ldloc    'p2/1'
    ldind.i1
    xor
    stind.i1
L_28:
    ldloc    'p1/0'
    ldc.i4    1
    add
    stloc    'p1/0'
    ldloc    'p2/1'
    ldc.i4    1
    sub
    stloc    'p2/1'
// Line 11:        for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)

L_26:
    ldloc    'p2/1'
    ldloc    'p1/0'
    bgt 'L_25'

L_27:
// Line 16:        }

    ldarg    'str'
// Line 18:    }

L_18:
    ret

}
.method public hidebysig static void 'floatToBinary'(float32 'f' ,
void* 'str' , int32 'numeroDeBits' ) cil managed
{
// Line 20:    void floatToBinary(float f, char *str, int numeroDeBits)

    .maxstack    4
    .locals(
        [0]        int32 'i/0',
        [1]        int32 'strIndex/1',
        [2]        valuetype 'Program.FloatToBinaryø__anontype_2486130647_0' 'u/2'
    )

L_41:
// Line 22:        int i = 0;

    ldloca    'i/0'
    ldc.i4    0
    stind.i4
// Line 23:        int strIndex = 0;

    ldloca    'strIndex/1'
    ldc.i4    0
    stind.i4
// Line 29:        u.f = f;

    ldloca    'u/2'
    ldarg    'f'
    stind.r4
// Line 30:        memset(str, '0', numeroDeBits);

    ldarg    'str'
    ldc.i4    48
    ldarg    'numeroDeBits'
    conv.u4
    call    void* 'memset'(void*, int32, uint32)
    pop
// Line 31:    

    ldc.i4    0
    stloc    'i/0'
    br 'L_45'

L_44:
// Line 33:        {

// Line 34:            str[strIndex++] = (u.i & (1 << 0)) ? '1' : '0';

    ldloc    'strIndex/1'
    ldarg    'str'
    add
    ldloc    'strIndex/1'
    ldc.i4    1
    add
    stloc    'strIndex/1'
    ldloca    'u/2'
    ldind.u4
    ldc.i4    1
    and
    brfalse 'L_56'

    ldc.i4    49
    br 'L_57'

L_56:
    ldc.i4    48
L_57:
    conv.i1
    stind.i1
// Line 35:            u.i >>= 1;

    ldloca    'u/2'
    ldloca    'u/2'
    ldind.u4
    ldc.i4    1
    shr.un
    stind.i4
L_47:
    ldloc    'i/0'
    ldc.i4    1
    add
    stloc    'i/0'
// Line 32:        for (i = 0; i < numeroDeBits; i++)

L_45:
    ldloc    'i/0'
    ldarg    'numeroDeBits'
    blt 'L_44'

L_46:
// Line 36:        }

    ldloc    'strIndex/1'
    ldarg    'str'
    add
    ldc.i4    0
    stind.i1
// Line 39:      

    ldarg    'str'
    call    void* Program.FloatToBinary::'strrev_t'(void*)
    starg    'str'
// Line 41:    }

L_42:
    ret

}

    .field public static void *'__stdin'

    .field public static void *'__stdout'

    .field public static void *'__stderr'

    .field public static void *'_pctype'
.method private hidebysig static void '$Main'() cil managed {
    .entrypoint
    .locals (
        [0] int32 'argc',
        [1] void * 'argv',
        [2] void * 'environ',
        [3] void * 'newmode'
    )
    .maxstack 5

    call void *'__pctype_func'()
    stsfld void * Program.FloatToBinary::_pctype
    call void *'__iob_func'()
    dup
    stsfld void * Program.FloatToBinary::__stdin
    dup
    ldc.i4 32
    add
    stsfld void * Program.FloatToBinary::__stdout
    ldc.i4 64
    add
    stsfld void * Program.FloatToBinary::__stderr
    ldloca 'argc'
    ldloca 'argv'
    ldloca 'environ'
    ldc.i4  0
    ldloca 'newmode'
    call void __getmainargs(void *, void *, void *, int32, void *);
    ldloc 'argc'
    ldloc 'argv'
    call int32 Program.FloatToBinary::main(int32, void *)
    call void exit(int32)
    ret
}
.class nested private value explicit ansi sealed 'int8[]' {.pack 1 .size 1}
.class nested public value explicit
auto sequential ansi sealed '__anontype_2486130647_0' {.pack 4 .size 4}
.class nested public value explicit auto sequential ansi sealed 'int32[2]' {.pack 1 .size 8 }
.class enum nested public auto ansi sealed 'orient' {
    .field public static literal valuetype Program.FloatToBinary/orient __or_unspecified = int32(0)
    .field public static literal valuetype Program.FloatToBinary/orient __or_narrow = int32(1)
    .field public static literal valuetype Program.FloatToBinary/orient __or_wide = int32(2)
    .field public specialname rtspecialname int32 value__
}
}
}
.method private hidebysig static void * __GetErrno() cil managed {
    .maxstack 1

    call void * '_errno'()
    ret
}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
void* 'memset'(void*, int32, uint32) preservesig {}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
uint32 'strlen'(void*) preservesig {}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
vararg int32 'scanf'(void*) preservesig {}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
void 'exit'(int32) preservesig {}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
vararg int32 'printf'(void*) preservesig {}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
void '__getmainargs'(void*, void*, void*, int32, void*) preservesig {}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
void* '__pctype_func'() preservesig {}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
void* '_errno'() preservesig {}
.method public hidebysig static pinvokeimpl("msvcrt.dll" cdecl)
void* '__iob_func'() preservesig {}

為了執行生成的EXE / DLL,有兩個可執行的DLL很有必要,這樣你可以在C:\orangec\bin\中得到這兩個DLL,你只要複製DLL到相同EXE資料夾,並執行生成的EXE。

構建一個簡單的GUI應用程式

編譯器還不支援所有建立有Windows GUI的複雜程式,但可以編譯簡單程式,在這個例子中,讓我們建立一個簡單的視窗。

*注*:為了編譯程式碼來使用圖形介面,此時我們仍然需要宣告主要部分。

在這個簡單的示例中,我們建立了一個C檔案,叫做:window.c

#include <windows.h>
#include <stdio.h>

const char g_szClassName[] = "WindowClass";

void createButtons(HWND hwnd)
{
    CreateWindow("button", "Beep",
        WS_VISIBLE | WS_CHILD,
        20, 50, 80, 25,
        hwnd, (HMENU)1, NULL, NULL);

    CreateWindow("button", "Quit",
        WS_VISIBLE | WS_CHILD,
        120, 50, 80, 25,
        hwnd, (HMENU)2, NULL, NULL);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:
        createButtons(hwnd);
        break;
    case WM_COMMAND:
    {
        if (LOWORD(wParam) == 1)
            Beep(40, 50);

        if (LOWORD(wParam) == 2) {
            MessageBox(hwnd, "Goodbye, cruel world!", "Note", MB_OK);
            PostQuitMessage(0);
        }

        break;
    }
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hwnd = CreateWindowExA(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "Test window in .Net!! :) ",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 230, 150,
        NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

int main(int argc, char* argv[])
{
    STARTUPINFOA si;
    GetStartupInfoA(&si);
    int ret = WinMain(GetModuleHandleA(NULL), NULL, "", (si.dwFlags & 1) ? si.wShowWindow : 10);
    return ret;
}

要生成這個原始碼,報告編譯器libs.在源中使用了什麼是必要的,因此,在命令列中生成原始碼是這樣的:

occil /Lkernel32 /Luser32 /9 window.c

生成之後,我們就可以執行應用程式:  )

在C#中建立並使用來自於C語言程式碼的DLL

現在我們知道如何從C語言程式碼建立一個.NET EXE。下面讓我們從C語言程式碼建立一個DLL,並和你的C#程式碼一起使用它。

用C語言建立一個簡單的堆疊,為此,建立一個名為“stack.c”的C檔案,並在檔案中插入下面的程式碼:

#include <stdio.h>
#include <stdlib.h>

typedef struct _stack_
{
    int size;
    int totalitems;
    int* stack;
} stack;

stack* pl_initastack(int size);
void pl_push(stack* pl, int elemento, int* success);
int pl_pop(stack* pl, int* success);
int pl_top(stack *pl, int* success);
int pl_base(stack* pl, int *success);
int pl_stackfull(stack* pl);
int pl_stackempty(stack* pl);
void pl_freestack(stack *pl);
void pl_cleanstack(stack *pl);

stack* pl_initastack(int size)
{
    stack* pl = (stack*)malloc(sizeof(stack));
    pl->stack = (int*)malloc(sizeof(int) * size);
    pl->size = size;
    pl->totalitems = 0;
    return pl;
}

void pl_push(stack* pl, int elemento, int* success)
{
    if (!pl_stackfull(pl))
        pl->stack[pl->totalitems++] = elemento;
    else
        *success = 0;
}

int pl_pop(stack* pl, int* success)
{
    if (!pl_stackempty(pl))
    {
        *success = 1;
        return pl->stack[--pl->totalitems];
    }
    else
    {
        *success = 0;
        return -1;
    }
}

int pl_top(stack *pl, int* success)
{
    if (pl_stackempty(pl))
    {
        *success = 0;
        return -1;
    }
    else
    {
        *success = 1;
        return pl->stack[pl->totalitems - 1];
    }
}

int pl_base(stack* pl, int *success)
{
    if (pl_stackempty(pl))
    {
        *success = 0;
        return -1;
    }
    else
    {
        *success = 1;
        return pl->stack[0];
    }
}

int pl_stackfull(stack* pl)
{
    return pl->totalitems >= pl->size;
}

int pl_stackempty(stack* pl)
{
    return pl->totalitems == 0;
}

void pl_freestack(stack* pl)
{
    free(pl->stack);
    free(pl);
}

void pl_cleanstack(stack *pl)
{
    pl->stack = malloc(sizeof(int) * pl->size);
    pl->totalitems = 0;
}

現在,你需要用選項/Wd生成這個原始碼。這將告訴編譯器你想要生成一個DLL,所以為了建立這個檔案,我們使用這個命令列:

occil /ostackdll.il /c /Wd /9 /NStackLib.Stack stack.c

建立stack.c後,讓我們構建生成的IL程式碼到DLL:

ilasm /DLL stackdll.il

現在,讓我們建立C#專案。在這篇文章中,我建立了一個.NET 4.0的C#專案。

對此,你可以使用OCC生成的DLL,你需要在C#專案中做一些設定:

  • Enable Unsafe code
  • Plataform target: x86

在設定這些選項後,在引用中新增stack.dll,並寫程式碼來使用DLL,在這種情況下,我寫了這個簡單的示例程式:

using System;

namespace Stack
{
    unsafe class Program
    {
        static void Main(string[] args)
        {
            void* stk = null;
            stk = StackLib.Stack.pl_initastack(5);

            int success = 1;
            Console.WriteLine("Pushing values to stack...");
            for(int i=0; (success == 1); i++)
            {
                int val = i * 10;
                StackLib.Stack.pl_push(stk, val, &success);
            }

            Console.WriteLine("Base value in stack: {0}", StackLib.Stack.pl_base(stk, &success));
            Console.WriteLine("Top value in stack.: {0}", StackLib.Stack.pl_top(stk, &success));

            Console.WriteLine("Poping values from stack");
            while(true)
            {
                int val = StackLib.Stack.pl_pop(stk, &success);
                if (success == 0)
                    break;
                Console.WriteLine("{0}", val);
            }

            StackLib.Stack.pl_freestack(stk);
            stk = null;
        }
    }
}

在你構建EXE後,不要忘了複製在orangec資料夾的BIN資料夾中的兩個DLL。

使用SQLite

現在我們知道如何在C語言中建立並使用來自於原始碼的DLL,讓我們使用SQLite!

你可以在資料夾 \samples\sqlite3中找到SQLite原始碼。

要構建SQLite原始碼,有必要使用此命令列:

occil /9 /Wd /Lkernel32 sqlite3.c /Nsqlite3.sqlite

在建立SQLite後,建立一個C#或任何其他.NET專案,隨你選擇,在專案中新增SQLite的編譯DLL的引用,設定專案型別為x86以及在必要時啟用不安全模式,在我的情況中,我建立了一個簡單的C#專案,並隨便弄了個小程式來使用SQLite:

using System;
using System.IO;

using sqlite3;
using lsmsilcrtl;

namespace sqliteil
{
    unsafe class Program
    {
        static string[] Names { get; } = new string[]
        {
            "Bob",
            "Tom",
            "Carlos",
            "Marcos",
            "Alexandre",
            "Alex",
            "Morgana",
            "Maria",
            "Jose",
            "Joao",
            "Marcos",
            "Gustavo",
            "Roberto",
            "Rodrigo",
            "Teste"
        };

        static int Main(string[] args)
        {
            String dbName = "dbtest.db";

            if (File.Exists(dbName))
                File.Delete(dbName);

            void* db;
            // Create the database
            int rc = sqlite.sqlite3_open(CString.ToPointer(dbName), &db);
            if (rc != 0)
            {
                Console.WriteLine("Fail to create the database : (");
                return -1;
            }

            // Create the table
            void* stmt;
            sqlite3.sqlite.sqlite3_prepare_v2(db, CString.ToPointer("CREATE TABLE demo (name TEXT, age INTEGER);"), -1, &stmt, null);
            rc = sqlite.sqlite3_step(stmt);
            if (rc != 101)
            {
                Console.WriteLine("Fail to create the table : (");
                return -1;
            }
            sqlite.sqlite3_finalize(stmt);

            // Insert some data in table
            foreach (var name in Names)
            {
                var insertLine = String.Format("insert into demo (name, age) values ('{0}', {1});", name, new Random().Next(1, 99));
                var query = CString.ToPointer(insertLine);
                sqlite.sqlite3_prepare_v2(db, query, insertLine.Length, &stmt, null);
                rc = sqlite.sqlite3_step(stmt);
                if (rc != 101)
                {
                    Console.WriteLine("Fail to insert the name: {0}", name);
                }
                sqlite.sqlite3_finalize(stmt);
            }

            // Read the inserted data...
            var select = "SELECT * FROM demo;";
            rc = sqlite.sqlite3_prepare_v2(db, CString.ToPointer(select), select.Length, &stmt, null);
            if(rc == 0)
            {
                bool done = false;
                while(!done)
                {
                    switch(rc = sqlite.sqlite3_step(stmt))
                    {
                        case 5:
                        case 101:
                            done = true;
                            break;
                        case 100:
                            {
                                string name = new CString(sqlite.sqlite3_column_text(stmt, 0)).ToString();
                                int age = sqlite.sqlite3_column_int(stmt, 1);
                                Console.WriteLine("Name: {0} -- Age: {1}", name, age);
                                rc = 0;
                            }
                            break;
                        default:
                            done = true;
                            break;
                    }
                }
            }

            sqlite.sqlite3_close(db);
            return 0;
        }
    }
}

該專案在SQLite測試資料夾內。

譯文連結:http://www.codeceo.com/article/compiling-c-code-to-dotnet.html
英文原文:Compiling your C code to .NET
翻譯作者:碼農網 – 小峰
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章