2016-08-05 131 views
1

我有一個從Squeak生成的.c文件,我需要編譯爲一個dll作爲插件使用,但我不知道如何。我試過搜索互聯網,但我能找到的所有信息都是關於如何將c#和C++編譯爲dll的信息。已生成的代碼如下:編譯C代碼到動態鏈接庫

/* Automatically generated from Squeak on (13 July 2016 9:46:45 pm) */ 

#if defined(WIN32) || defined(_WIN32) || defined(Win32) 
#ifdef __cplusplus 
    #define DLLEXPORT extern "C" __declspec(dllexport) 
#else 
    #define DLLEXPORT __declspec(dllexport) 
#endif /* C++ */ 
#else 
#define DLLEXPORT 
#endif /* WIN32 */ 

#include "sqVirtualMachine.h" 

/* memory access macros */ 
#define byteAt(i) (*((unsigned char *) (i))) 
#define byteAtput(i, val) (*((unsigned char *) (i)) = val) 
#define longAt(i) (*((int *) (i))) 
#define longAtput(i, val) (*((int *) (i)) = val) 

#include <string.h> 

/*** Variables ***/ 
struct VirtualMachine* interpreterProxy; 
const char *moduleName = "TestPlugin 13 July 2016 (e)"; 

/*** Functions ***/ 
DLLEXPORT int primitiveAdd(void); 
DLLEXPORT int primitiveFetchString(void); 
DLLEXPORT int setInterpreter(struct VirtualMachine* anInterpreter); 

DLLEXPORT int primitiveAdd(void) { 
    int operand1; 
    int operand2; 
    int result; 

    operand1 = interpreterProxy->stackIntegerValue(1); 
    operand2 = interpreterProxy->stackIntegerValue(0); 
    if (interpreterProxy->failed()) { 
     return 0; 
    } 
    result = operand1 + operand2; 
    interpreterProxy->popthenPush(3, ((result << 1) | 1)); 
    return 0; 
} 

DLLEXPORT int primitiveFetchString(void) { 
    int in; 
    int i; 
    int count; 
    int resultOop; 
    char* src; 
    char* dst; 
    char s0[] = "zero"; 
    char s1[] = "non-zero"; 

    in = interpreterProxy->stackIntegerValue(0); 
    if (interpreterProxy->failed()) { 
     return 0; 
    } 
    if (in == 0) { 
     src = s0; 
    } else { 
     src = s1; 
    } 
    count = strlen(src); 
    resultOop = interpreterProxy->instantiateClassindexableSize(interpreterProxy->classString(), count); 
    dst = ((char *) (interpreterProxy->firstIndexableField(resultOop))); 
    for (i = 0; i <= (count - 1); i += 1) { 
     dst[i] = (src[i]); 
    } 
    interpreterProxy->popthenPush(2, resultOop); 
    return 0; 
} 

DLLEXPORT int setInterpreter(struct VirtualMachine* anInterpreter) { 
    int ok; 

    interpreterProxy = anInterpreter; 
    ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR; 
    if (ok == 0) { 
     return 0; 
    } 
    ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR; 
    return ok; 
} 

注:這只是TestPlugin代碼;我實際上正在構建一個像這樣的dll,以加快我吱吱聲中運行緩慢的吱吱聲代碼的區域。

回答

1

您的第一站應該是OpenSmalltalk virtual machine repository。該存儲庫包含有關如何編譯虛擬機及其插件的全面文檔。如果你想分發你的插件與虛擬機,那麼這可能是你需要的。

另一方面,您可以自己編譯插件並將其複製到插件目錄。虛擬機將嘗試根據請求加載插件,並可以在插件目錄位於其搜索路徑中時找到它。要自己編譯插件,您需要構建工具鏈。這可以是生成共享庫的任何東西(Visual Studio,XCode,autotools等)。

有你需要記住一些事情:

  1. 編譯爲共享和通用
  2. 編譯成32位
  3. 在C++的情況:導出符號,以防止名字改編

構建腳本的複雜性取決於您要編譯的庫。對於在VM編譯期間生成的插件的相當複雜的構建腳本(對於Windows),您可以查看PharoVM使用的CMake script for libgit2

不幸的是,共享庫編譯沒有銀彈。隨着圖書館及其用戶的需求發生變化,構建過程及其複雜性也會發生變化。對於依賴關係尤其如此(例如,當使用pkg-config爲所需的庫搜索常用安裝路徑時)。然而,從你的代碼來看,我認爲它不應該是一個大問題。我的建議:花時間爲您的插件創建一個CMake腳本。這可能比手動運行編譯器更困難,但它可以作爲編譯文檔,如果您需要在另一個平臺上進行編譯,這將是一個很大的幫助。