在python中,在什么情况下SWIG比ctypes更适合在共享库中调用入口点?假设您还没有SWIG接口文件.
两者的性能指标是什么?
我目前正在用C++编写一个应用程序,发现它的一些功能可以更好地用Haskell编写.我已经看过从C代码调用Haskell的说明,但是可以用C++做同样的事情吗?
编辑:澄清一下,我正在寻找的是一种将Haskell代码编译成外部库的方法,g ++可以与C++中的目标代码链接.
更新:我已经为其他感兴趣的人提供了一个工作示例(也是我不会忘记的).
我有一个关于在Haskell FFI和GHC的交互模式的问题再次.
考虑FFISo.hs
:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import qualified Data.ByteString.Char8 as B
import FFIFun.Foo
main :: IO ()
main = do
B.putStrLn "main"
callMeFromC
callMeFromHaskell
return ()
Run Code Online (Sandbox Code Playgroud)
c.c
:
#include <stdio.h>
void callMeFromC(void);
void callMeFromHaskell(void)
{
printf("callMeFromHaskell\n");
callMeFromC();
}
Run Code Online (Sandbox Code Playgroud)
FFIFun/Foo.hs
:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module FFIFun.Foo where
import qualified Data.ByteString.Char8 as B
foreign import ccall "callMeFromHaskell"
callMeFromHaskell :: IO ()
foreign export ccall callMeFromC :: IO ()
callMeFromC …
Run Code Online (Sandbox Code Playgroud) 哦,我的话,我是个傻瓜. 在调用函数时,我只是省略了第二个和第三个参数.像一个傻瓜.因为那就是我.原来愚蠢的问题如下:
这似乎是一件很常见的事情,但我找不到相关的教程,而且我太无知了,Numpy
并且ctypes
自己弄清楚了.
我在文件中有一个C函数ctest.c
.
#include <stdio.h>
void cfun(const void * indatav, int rowcount, int colcount, void * outdatav) {
//void cfun(const double * indata, int rowcount, int colcount, double * outdata) {
const double * indata = (double *) indatav;
double * outdata = (double *) outdatav;
int i;
puts("Here we go!");
for (i = 0; i < rowcount * colcount; ++i) {
outdata[i] = indata[i] * 2;
}
puts("Done!");
}
Run Code Online (Sandbox Code Playgroud)
(正如你可能猜到的那样,我最初的论点是double*而不是void*,但是无法弄清楚在Python方面该怎么做.我当然喜欢把它们改回来,但我并不挑剔只要它有效.)
我从中创建了一个共享库.gcc -fPIC …
我正在尝试获取C库返回的C字符串,并通过FFI将其转换为Rust字符串.
mylib.c
const char* hello(){
return "Hello World!";
}
Run Code Online (Sandbox Code Playgroud)
main.rs
#![feature(link_args)]
extern crate libc;
use libc::c_char;
#[link_args = "-L . -I . -lmylib"]
extern {
fn hello() -> *c_char;
}
fn main() {
//how do I get a str representation of hello() here?
}
Run Code Online (Sandbox Code Playgroud) 我一直在努力在Haskell中编写Windows服务应用程序.
服务应用程序由Windows服务控制管理器执行.启动后,它会对StartServiceCtrlDispatcher进行阻塞调用,该调用提供了一个回调函数,用作服务的主函数.
该服务的主要功能是注册第二个回调来处理传入的命令,如启动,停止,继续等.它通过调用RegisterServiceCtrlHandler来完成.
我能够编写一个注册服务主函数的程序.然后,我可以将程序安装为Windows服务,并从服务管理控制台启动它.该服务能够启动,将自身报告为正在运行,然后等待传入的请求.
问题是我无法调用我的服务处理函数.查询服务状态显示它正在运行,但是一旦我发送"停止"命令,窗口会弹出一条消息说:
Windows could not stop the Test service on Local Computer.
Error 1061: The service cannot accept control messages at this time.
Run Code Online (Sandbox Code Playgroud)
根据MSDN文档,StartServiceCtrlDispatcher函数会阻塞,直到所有服务报告它们已停止.在调用服务主函数之后,调度程序线程应该等到服务控制管理器发送命令,此时应该由该线程调用处理函数.
以下是我正在尝试做的非常简化的版本,但它演示了我的处理程序函数未被调用的问题.
首先,一些名称和进口:
module Main where
import Control.Applicative
import Foreign
import System.Win32
wIN32_OWN_PROCESS :: DWORD
wIN32_OWN_PROCESS = 0x00000010
sTART_PENDING, rUNNING :: DWORD
sTART_PENDING = 0x00000002
rUNNING = 0x00000004
aCCEPT_STOP, aCCEPT_NONE :: DWORD
aCCEPT_STOP = 0x00000001
aCCEPT_NONE = 0x00000000
nO_ERROR …
Run Code Online (Sandbox Code Playgroud) 我刚刚花了大约一周的时间来搞清楚如何从C#执行C++代码作为我日常工作的一部分.我们花了很长时间才弄明白,但最终的解决方案相当简单.
现在我很好奇......从C#调用Haskell会有多难?(注意:这是从 C#调用Haskell ,而不是相反.所以主要的可执行文件是C#.)
如果它真的很难,我不会打扰.但如果它相当容易,我可能不得不玩它...
基本上,我们编写了一些C++代码.在Windows上,它被编译成一个DLL,在Linux上它被编译成一个共享对象(*.so
).然后在C#端你做一个DllImport
并写一些手动内存管理代码,如果你试图通过任何非常重要的事情.(例如,数组,字符串等)
我知道GHC应该支持在两个平台上构建共享库,但我不确定技术细节.导出内容的语法是什么,调用者是否必须先做一些特殊的事情来初始化DLL?
具体来说:假设存在一个函数foobar :: FilePath -> IO Int32
.有人可以把一个小草图放在一起显示:
foobar
.我不太担心C#端的实际语法; 我想我或多或少地对此感到困惑.
PS我做过简要介绍hs-dotnet
,但这似乎是Windows特定的.(即,不适用于Mono,因此无法在Linux上运行.)
如果您有可能拥有一个同时使用Haskell和C++的应用程序.你会让Haskell管理什么层,你会让C++管理哪些层?
有没有人做过这样的联想,(当然)?
(Haskell站点告诉它非常简单,因为Haskell有一个模式,可以通过gcc在C中编译)
起初我认为我会将所有I/O操作保留在C++层中.以及GUI管理.
这是一个非常模糊的问题,但是当我计划学习Haskell时,我正在考虑将一些工作委托给Haskell代码(我在实际编写中学习),并且我想选择一些我将看到Haskell好处的部分.
我已经定义了一个ctypes
类和一个相关的便利函数,如下所示:
class BNG_FFITuple(Structure):
_fields_ = [("a", c_uint32),
("b", c_uint32)]
class BNG_FFIArray(Structure):
_fields_ = [("data", c_void_p),
("len", c_size_t)]
# Allow implicit conversions from a sequence of 32-bit unsigned ints
@classmethod
def from_param(cls, seq):
return seq if isinstance(seq, cls) else cls(seq)
def __init__(self, seq, data_type = c_float):
array_type = data_type * len(seq)
raw_seq = array_type(*seq)
self.data = cast(raw_seq, c_void_p)
self.len = len(seq)
def bng_void_array_to_tuple_list(array, _func, _args):
res = cast(array.data, POINTER(BNG_FFITuple * array.len))[0]
return res
convert = lib.convert_to_bng
convert.argtypes = (BNG_FFIArray, …
Run Code Online (Sandbox Code Playgroud) 如果我想调用多个C函数,每个函数取决于前一个函数的结果,是否最好创建一个处理三个调用的包装器C函数?它会花费与使用Haskell FFI而不转换类型相同的成本吗?
假设我有以下Haskell代码:
foo :: CInt -> IO CInt
foo x = do
a <- cfA x
b <- cfB a
c <- cfC c
return c
Run Code Online (Sandbox Code Playgroud)
每个函数cf*
都是C调用.
在性能方面,创建单个C函数cfABC
并在Haskell中只进行一次外部调用会更好吗?
int cfABC(int x) {
int a, b, c;
a = cfA(x);
b = cfB(a);
c = cfC(b);
return c;
}
Run Code Online (Sandbox Code Playgroud)
Haskell代码:
foo :: CInt -> IO CInt
foo x = do
c <- cfABC x
return c
Run Code Online (Sandbox Code Playgroud)
如何衡量Haskell的C调用的性能成本?不是C函数本身的成本,而是从Haskell到C的"上下文切换"的成本.