将c代码编译为动态链接库

时间:2016-08-05 04:47:23

标签: c dll squeak

我有一个从Squeak生成的.c文件,我需要编译成一个dll用作插件,但我不知道如何。我试过在互联网上搜索,但我能找到的是有关如何将c#和c ++编译成dll的信息。生成的代码如下:

/* 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 个答案:

答案 0 :(得分:1)

你的第一站应该是OpenSmalltalk virtual machine repository。存储库包含有关如何编译虚拟机及其插件的全面文档。如果您想使用虚拟机分发插件,那么这很可能是您需要的。

另一方面,您可以自己编译插件并将其复制到plugins目录。 VM将根据请求尝试加载插件,并且可以在插件目录位于其搜索路径中时找到它。要自己编译插件,您需要一个构建工具链。这可以是生成共享库的任何东西(Visual Studio,XCode,autotools等)。

您需要记住一些事项:

  1. 编译为共享和通用
  2. 编译为32位
  3. 在C ++的情况下:导出符号以防止名称错位
  4. 构建脚本的复杂性取决于您要编译的库。对于在VM编译期间生成的插件的相当复杂的构建脚本(对于Windows),您可以查看PharoVM使用的CMake script for libgit2

    不幸的是,共享库编译没有灵丹妙药。随着库及其用户的需求发生变化,构建过程及其复杂性也会发生变化。对于依赖项尤其如此(例如,当使用pkg-config搜索所需库的公共安装路径时)。从你的代码来看,我认为它不应该是一个大问题。我的建议:花点时间为你的插件创建一个CMake脚本。它可能比手动运行编译器更难,但它作为如何执行编译的文档,如果你需要在另一个平台上编译或为另一个平台编译,将会是一个很大的帮助。