Here's my situation:
I would like to call ffmpeg's av_free_packet
function:
// avformat.h
static inline void av_free_packet(AVPacket *pkt)
{
if (pkt && pkt->destruct)
pkt->destruct(pkt);
}
But unfortunately this function is static inline
, and so doesn't really appear in the linked library.
However, it is a very simple function, which I could reimplement in Haskell. And that's what I can't figure out how to do. Here's a partial attempt (.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 = ?
For now I could resort to implementing this function in C (by just calling the original), but it seems to me that calling function pointers should be possible somehow..
From The Haskell 98 Foreign Function Interface 1.0,
Dynamic import.
The type of a dynamic stub has to be of the form
(FunPtr ft) -> ft
, whereft
may be any foreign type.As an example, consider
foreign import ccall "dynamic" mkFun :: FunPtr (CInt -> IO ()) -> (CInt -> IO ())
The stub factory
mkFun
converts any pointer to a C function that gets an integer value as its only argument and does not have a return value into a corresponding Haskell function.
In your case, the usage would look something like the following.
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
A small example to demonstrate that this (ephemient's answer) actually works (following gbacon's concern):
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;
}
Haskell:
{-# 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
This works for me - prints 3 % 5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With