如何从Sage调用C代码(或编译库)?

如果你有一些C/C++代码,你想从SAGE中调用,供你自己使用,这个文档是给你的。

  • 你想吗 继续 通过将接口添加到Sage的代码中?(更复杂的)指令是 available here .

从hello.c调用“hellou world()”

假设您有一个名为 ~/my_dir/hello.c 包含:

#include <stdio.h>

void hello_world(){
    printf("Hello World\n");
}

为了从Sage调用这个函数,必须创建一个Cython文件(即扩展名为.pyx的文件)。在这里, ~/my_dir/hello_sage.pyx 包含描述要调用的函数的签名的标头:

cdef extern from "hello.c":
    void hello_world()

def my_bridge_function():
    hello_world() # This is the C function from hello.c

现在可以在Sage中加载这个文件,并通过Python函数调用C代码 my_bridge_function ::

sage: %runfile hello_sage.pyx
Compiling ./hello_sage.pyx...
sage: my_bridge_function()
Hello World

参数和返回值

使用更复杂的参数和返回值调用函数的方式是相同的。想了解更多关于赛顿语的知识, click here

下面的示例定义了一个获取和返回的函数 int * 指针,并涉及一些内存分配。C代码定义了一个函数,其目的是将两个向量的和作为第三个向量返回。

The C file (double_vector.c)

#include <string.h>

int * sum_of_two_vectors(int n, int * vec1, int * vec2){
  /*
     INPUT : two arrays vec1,vec2 of n integers
     OUTPUT: an array of size n equal to vec1+vec2
  */
  int * sum = (int *) malloc(n*sizeof(int));
  int i;

  for(i=0;i<n;i++)
    sum[i] = vec1[i] + vec2[i];
  return sum;
}

The Cython file (double_vector_sage.pyx)

cdef extern from "double_vector.c":
    int * sum_of_two_vectors(int n, int * vec1, int * vec2)

from libc.stdlib cimport malloc, free

def sage_sum_of_vectors(n, list1, list2):
    cdef int * vec1 = <int *> malloc(n*sizeof(int))
    cdef int * vec2 = <int *> malloc(n*sizeof(int))

    # Fill the vectors
    for i in range(n):
        vec1[i] = list1[i]
        vec2[i] = list2[i]

    # Call the C function
    cdef int * vec3 = sum_of_two_vectors(n,vec1,vec2)

    # Save the answer in a Python object
    answer = [vec3[i] for i in range(n)]

    free(vec1)
    free(vec2)
    free(vec3)

    return answer

Sage的召唤 ::

sage: %runfile double_vector_sage.pyx
Compiling ./double_vector_sage.pyx...
sage: sage_sum_of_vectors(3,[1,1,1],[2,3,4])
[3, 4, 5]

从编译库调用代码

程序又很相似。出于我们的目的,我们从该文件构建一个库 ~/my_dir/hello.c

 #include <stdio.h>

 void hello_world(){
     printf("Hello World\n");
}

我们还需要一个 ~/my_dir/hello.h 头文件:

void hello_world();

我们现在可以 编译它 作为一个类库:

[user@localhost ~/my_dir/] gcc -c -Wall -Werror -fpic hello.c
[user@localhost ~/my_dir/] gcc -shared -o libhello.so hello.o

我们现在唯一需要的文件是 hello.hlibhello.so (如果您愿意,可以删除其他部分)。我们现在必须指出 .so.h 文件头中的文件 ~/my_dir/hello_sage.pyx 文件:

# distutils: libraries = /home/username/my_dir/hello

cdef extern from "hello.h":
    void hello_world()

def my_bridge_function():
    hello_world() # This is the C function from hello.c

注解

说明书 # distutils: libraries = /home/username/my_dir/hello 指示库实际已命名 /home/username/my_dir/hello . 根据你的需要改变它。有关这些说明的详细信息,请参阅http://cython.readthedocs.io/en/latest/src/reference/compilation.html配置-c构建

我们现在可以 load 这个文件在Sage和 call 功能:

sage: %runfile hello_sage.pyx
Compiling ./hello_sage.pyx...
sage: my_bridge_function()
Hello World