【问题标题】:How to use a C callback from C#?如何使用 C# 中的 C 回调?
【发布时间】:2012-04-15 23:08:56
【问题描述】:

这是库 Secret Rabbit Code (aka libsamplerate) 的 .NET 包装器,当在 CallbackRead 中调用 src_callback_read 时:AccessViolationException - 试图读取或写入受保护的内存 em>。

来自 C 头文件:

/* Opaque data type SRC_STATE. */
typedef struct SRC_STATE_tag SRC_STATE ;

typedef long (*src_callback_t) (void *cb_data, float **data) ;

SRC_STATE* src_callback_new (src_callback_t func, int converter_type, int channels,                 int *error, void* cb_data) ;

long src_callback_read (SRC_STATE *state, double src_ratio, long frames, float *

然后我创建了以下内容:

调用C库的C++/CLI类库:

public delegate long SRCCallback ( void *cb_data, float **data ) ;

static  IntPtr CallbackNew ( SRCCallback ^func, RabbitConverter converter_type, int channels, int *error, void* cb_data )
        {
            src_callback_t* cb = ( src_callback_t* ) &func;
            SRC_STATE* state =  src_callback_new ( *cb, ( int ) converter_type, channels, error, cb_data );
            IntPtr ptr = IntPtr ( state );
            return ptr;
        }

static long CallbackRead ( IntPtr  src_state, double src_ratio, long frames , float * data )
        {
            void* toPointer = src_state.ToPointer();
            SRC_STATE* state = ( SRC_STATE* ) toPointer;
            long l = src_callback_read ( state, src_ratio, frames, data );
            return l;
        }

使用 C++/CLI 库的 C# 应用程序:

private static readonly unsafe SRCCallback _callback = target;

private static unsafe void Callback()
{
    var input = GetSine(1000.0d, 44100, 1);
    fixed (float* f = input)
    {
        RabbitError error = RabbitError.SRC_ERR_NO_ERROR;
        var @void = Rabbit.CallbackNew(_callback, RabbitConverter.SRC_SINC_BEST_QUALITY, 1, (int*) (&error),
                                        (void*) IntPtr.Zero);
        var callbackRead = Rabbit.CallbackRead(@void  , 1d, input.Length/2, f);
        if (callbackRead != input.Length)
        {
            // throw new InvalidOperationException();
        }
    }
}

private static unsafe int target(void* cb_data, float** data)
{
    return 9;
}

【问题讨论】:

  • “在这种情况下,任意意味着输入和输出采样率的比率可以是一个无理数”...我希望将此声音重新采样到 10000 \pi Hz,拜托!实际上,将信号重建信任给显然不知道有理数是什么的人会令我担心。
  • Ascension Systems:我尝试使用 ref 但没有成功。
  • Ben Voigt:那你知道替代方案吗? :-)

标签: c# c++


【解决方案1】:

我已使用以下方法修复它:

[System::Runtime::InteropServices::UnmanagedFunctionPointerAttribute ( CallingConvention::Cdecl )]
public delegate long SRCCallback ( void *cb_data, float **data ) ;

static  IntPtr CallbackNew ( SRCCallback ^ % func, RabbitConverter converter_type, int channels, int *error, void* cb_data ) { ... }

简而言之:现在它使用 C 调用约定和 C# ref 关键字。

【讨论】:

    猜你喜欢
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-12
    相关资源
    最近更新 更多