10

这是我的情况:

我想调用ffmpeg的av_free_packet函数:

// avformat.h
static inline void av_free_packet(AVPacket *pkt)
{
  if (pkt && pkt->destruct)
    pkt->destruct(pkt);
}

但不幸的是,这个函数是static inline,因此并没有真正出现在链接库中。

但是,它是一个非常简单的函数,我可以在 Haskell 中重新实现它。这就是我不知道该怎么做。这是部分尝试(.hsc):

av_free_packet :: Ptr AVPacket -> IO ()
av_free_packet pkt =
  when (nullPtr /= pkt) $ do
    destruct <- (#peek AVPacket, destruct) pkt :: IO (FunPtr (Ptr AVPacket -> IO ()))
    when (nullFunPtr /= destruct) $ funPtrToFun destruct pkt

funPtrToFun :: FunPtr a -> a
funPtrToFun = ?

现在我可以求助于在 C 中实现这个函数(通过调用原来的函数),但在我看来调用函数指针应该是可能的......

4

2 回答 2

8

Haskell 98 Foreign Function Interface 1.0

动态导入。

动态存根的类型必须是 形式(FunPtr ft) -> ft,其中ft可以是任何外来类型。

例如,考虑

foreign import ccall "dynamic"  
  mkFun :: FunPtr (CInt -> IO ()) -> (CInt -> IO ())

存根工厂mkFun将任何指向以整数值作为其唯一参数且没有返回值的 C 函数的指针转换为相应的 Haskell 函数。

在您的情况下,用法如下所示。

foreign import ccall "dynamic"
  funPktToNil:: FunPtr (Ptr AVPacket -> IO ()) -> Ptr AVPacket -> IO ()

av_free_packet :: Ptr AVPacket -> IO ()
av_free_packet pkt =
  when (nullPtr /= pkt) $ do
    destruct <- (#peek AVPacket, destruct) pkt
    when (nullFunPtr /= destruct) $ funPktToNil destruct pkt
于 2009-06-15T21:14:05.547 回答
7

一个小例子来证明这个(ehemient's answer)确实有效(遵循gbacon的关注):

C:

#include <stdio.h>

typedef void funcType(int, int);
typedef funcType * pFuncType;

void printer(int a, int b) {
  printf("%d %% %d\n", a, b);
}

pFuncType gimmeFunc(int dummy) {
  return printer;
}

哈斯克尔:

{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign.Ptr

foreign import ccall unsafe "gimmeFunc"
  c_gimmeFunc :: Int -> IO (FunPtr (Int -> Int -> IO ()))
foreign import ccall "dynamic"
  mkFunIntIntNil :: FunPtr (Int -> Int -> IO ()) -> Int -> Int -> IO ()

main :: IO ()
main = do
  fun <- c_gimmeFunc 1
  mkFunIntIntNil fun 3 5

这对我有用 - 打印3 % 5

于 2009-06-15T21:50:01.013 回答