將你的 C 語言程式碼編譯成 .NET
本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃!
介紹
通常情況下,對於那些使用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 ++編譯器的開發,或致力於以下連結的專案貢獻:
- 官方網站:http://ladso
ft.tripod.co m/index.html<wbr><wbr> - GitHub上的OrangeC / C ++編譯器和工具鏈:https://gith
ub.com/LADSo ft/OrangeC<wbr><wbr> - github上MSIL的OrangeC後端:https://gith
ub.com/LADSo ft/Simple-MS IL-Compiler<wbr><wbr><wbr>
構建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#編譯器)編譯器時必須的):
- omake netlib.lib
- omake
在執行這一命令後,你就有了occil.exe
使用OrangeC編譯器來生成MSIL程式碼
要使用編譯器,你只需下載這篇文章中提供的連結,建立資料夾C:\orangec,解壓該資料夾中的所有zip內容,開啟CMD,然後導航到C:\orangec資料夾,在orangec 資料夾中,type,config.bat後,當執行 config.bat檔案時,一個新的環境變數將在CMD
背景下建立,因此編譯器可以定位include資料夾。
*重點* ——在你的路徑中具備ILASM.EXE很有必要,為了做到這一點,你有兩個辦法把 ILASM放到你的路徑中:
- 執行VSVARS32.BAT
- 在你的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
翻譯作者:碼農網 – 小峰
[ 轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]
相關文章
- c語言if語句是如何變成彙編程式碼的?C語言
- 57段讓編譯器崩潰的C語言程式碼編譯C語言
- C語言編譯工具C語言編譯
- C語言程式碼區錯誤以及編譯過程C語言編譯
- C語言 - 條件編譯C語言編譯
- 將GO編繹成JavaScript,用GO語言來寫前端程式碼GoJavaScript前端
- C++ 能否成為你新的指令碼語言?C++指令碼
- c語言多檔案編譯C語言編譯
- C語言編譯全過程C語言編譯
- java編譯、編碼、語言設定Java編譯
- 使用C語言編寫貪食蛇程式原始碼C語言原始碼
- 用msys2編譯《自制程式語言》程式碼編譯
- C 語言常用錯誤程式碼釋義大全,讓你編譯執行報錯不是煩惱編譯
- 使用 Sublime Text 3 編譯 C 語言編譯
- C語言編譯器手機版C語言編譯
- 3- C語言編譯過程C語言編譯
- C語言編譯過程簡介C語言編譯
- C語言_來了解一下GCC編譯器編譯C可執行指令碼的過程C語言GC編譯指令碼
- 計算機程式語言的分類,解釋型語言、編譯型語言、指令碼語言的關係計算機編譯指令碼
- java開發C語言編譯器:為C語言提供API呼叫JavaC語言編譯API
- 09. C語言內嵌彙編程式碼C語言
- Linux下C語言編譯的問題LinuxC語言編譯
- 【開發語言】PHP、Java、C語言的編譯執行過程PHPJavaC語言編譯
- C語言-->(十四)結構體、巨集、編譯C語言結構體編譯
- 現代編譯原理C語言描述pdf編譯原理C語言
- 小C語言--詞法分析程式(編譯原理實驗一)C語言詞法分析編譯原理
- [譯] Go 語言實戰: 編寫可維護 Go 語言程式碼建議Go
- 編譯語言、解釋語言與指令碼語言之間的區別編譯指令碼
- C語言的編譯連結執行過程C語言編譯
- 淺談,C語言編譯原理的個人見解C語言編譯原理
- C語言的本質(32)——C語言與彙編之C語言內聯彙編C語言
- .NET 程式碼編譯過程編譯
- 關於編譯型語言程式碼優化的一點迷思編譯優化
- (嵌入式)Windows與Ubantu下的C語言程式的編譯執行WindowsC語言編譯
- 你不知道的C語言–第一篇——編譯和執行C語言編譯
- 通訊錄的c語言程式編輯C語言
- 第一個C語言編譯器是怎樣編寫的?C語言編譯
- 第一個 C 語言編譯器是怎樣編寫的?編譯