如何从Sage调用C代码(或编译后的库)?¶
如果您有一些C/C++代码想要从Sage调用以供自己使用,本文档适合您。
你想不想 contribute 通过将您的接口添加到Sage的代码?(更复杂的)指令是 available here 。
从hello.c调用“Hello_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
参数和返回值¶
使用更复杂的参数和返回值调用函数的工作方式与此相同。要了解更多关于Cython语言的信息, 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
Call from 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();
我们现在可以 compile it 作为类库:
[user@localhost ~/my_dir/] gcc -c -Wall -Werror -fpic hello.c
[user@localhost ~/my_dir/] gcc -shared -o libhello.so hello.o
我们现在唯一需要的文件是 hello.h
和 libhello.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#configuring-the-c-build
我们现在可以 load 此文件位于Sage和 call 功能::
sage: %runfile hello_sage.pyx
Compiling ./hello_sage.pyx...
sage: my_bridge_function()
Hello World