- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试从我的 .Net Core 应用程序调用 C 中的函数。深入了解一下,C 函数来自 libmpv render.h函数的头部如下所示:
int mpv_render_context_create(mpv_render_context **res, mpv_handle *mpv, mpv_render_param *params);
问题是我不知道如何从 C# 调用该函数。所以我尝试了以下方法:
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int mpv_render_context_create([Out] out IntPtr renderContext, IntPtr mpvHandle,
MpvRenderParam[] parameters);
自 **res
参数应该由函数更新我认为这是有意义的。我尝试使用以下内容进行调用:
var ptr = IntPtr.Zero;
var apiTypePtr = Marshal.StringToHGlobalAuto("opengl");
var i = mpv_render_context_create(out ptr, _mpvHandle, new []
{
new MpvRenderParam(MpvRenderParamType.ApiType, apiTypePtr),
new MpvRenderParam(MpvRenderParamType.Invalid, IntPtr.Zero
});
这给我带来了 AccessViolationException,事实上每次我调用 mpv_render_context_create
时方法我得到了相同的异常,所以当我说“它不起作用”时,我的意思是调用抛出了该异常。
所以我想也许我必须将其设为 ref 参数:
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int mpv_render_context_create(ref IntPtr renderContext, IntPtr mpvHandle,
MpvRenderParam[] parameters);
调用它时会导致相同的错误。
然后我读到另一个 stackoverflow 问题,我应该像下面这样传递裸 IntPtr:
[DllImport("mpv-1.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int mpv_render_context_create(IntPtr renderContext, IntPtr mpvHandle,
MpvRenderParam[] parameters);
但首先,它不再起作用,其次我如何从中得到结果?
那么我应该如何创建和调用该函数以便创建渲染上下文?
MpvRenderParam 声明如下:
[StructLayout(LayoutKind.Sequential)]
public struct MpvRenderParam
{
public MpvRenderParamType Type { get; }
public IntPtr Data { get; }
public MpvRenderParam(MpvRenderParamType type, IntPtr data)
{
Type = type;
Data = data;
}
}
以及MpvRenderParamType:
public enum MpvRenderParamType
{
Invalid = 0,
ApiType = 1,
InitParams = 2,
Fbo = 3,
FlipY = 4,
Depth = 5,
IccProfile = 6,
AmbientLight = 7,
X11Display = 8,
WlDisplay = 9,
AdvancedControl = 10,
NextFrameInfo = 11,
BlockForTargetTime = 12,
SkipRendering = 13,
DrmDisplay = 14,
DrmDrawSurfaceSize = 15,
DrmDisplayV2 = 15
}
我已经考虑了 Mattias Santoro 提供的所有资源,但我只是不完全确定如何将它们翻译成 C#,因为它是一种托管语言。我调用 mpv 函数的方法现在如下所示:
OpenGlControl.OpenGL.MakeCurrent();
IntPtr ptr;
var apiTypePtr = Marshal.StringToHGlobalAuto("opengl");
var opengl = new MpvOpenGlInitParams {get_proc_address = getProcAdress};
var size = Marshal.SizeOf(opengl);
var arr = new byte[size];
fixed (byte* arrPtr = arr)
{
Marshal.StructureToPtr(opengl, (IntPtr)arrPtr, true);
var parameters = new MpvRenderParam[]
{
new MpvRenderParam {Type = MpvRenderParamType.ApiType, Data = &apiTypePtr},
new MpvRenderParam {Type = MpvRenderParamType.OpenGlInitParams, Data = &arrPtr},
new MpvRenderParam {Type = MpvRenderParamType.Invalid, Data = null}
};
var i = mpv_render_context_create(&ptr, _mpvHandle, parameters);
}
MpvOpenGlInitParams:
[StructLayout(LayoutKind.Sequential)]
public struct MpvOpenGlInitParams
{
public delegate IntPtr GetProcAdressDelegate(IntPtr ctx, string name);
public GetProcAdressDelegate get_proc_address;
public IntPtr get_proc_address_ctx;
public string extra_exts;
}
可悲的是它仍然抛出同样的错误,我不确定我做错了什么,这真的很令人沮丧。
最佳答案
我已将代码放入此存储库中:(适用于 .net core 2.1 以及适用于 X64 的 sdl2 和 mpv dll) https://github.com/shodo/MPVCore.git
更新2:DOOOONEEEEE!首先,这是我的(真的很难看)代码。我不知道我所做的每件事是否都需要:
函数定义为:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int MpvRenderContextCreate(ref IntPtr context, IntPtr mpvHandler, IntPtr parameters);
private MpvRenderContextCreate _mpvRenderContextCreate;
和代码(它是 c++ sdl 示例的硬编码 Frankestein 以及 winform 和其他内容的一部分)
if (_mpvHandle != IntPtr.Zero)
_mpvTerminateDestroy(_mpvHandle);
LoadMpvDynamic();
if (_libMpvDll == IntPtr.Zero)
return;
_mpvHandle = _mpvCreate.Invoke();
if (_mpvHandle == IntPtr.Zero)
return;
_mpvInitialize.Invoke(_mpvHandle);
MpvOpenGlInitParams oglInitParams = new MpvOpenGlInitParams();
oglInitParams.get_proc_address = (ctx, name) => SDL.SDL_GL_GetProcAddress(name);
oglInitParams.get_proc_address_ctx = IntPtr.Zero;
oglInitParams.extra_exts = IntPtr.Zero;
var size = Marshal.SizeOf<MpvOpenGlInitParams>();
var oglInitParamsBuf = new byte[size];
fixed (byte* arrPtr = oglInitParamsBuf)
{
IntPtr oglInitParamsPtr = new IntPtr(arrPtr);
Marshal.StructureToPtr(oglInitParams, oglInitParamsPtr, true);
MpvRenderParam* parameters = stackalloc MpvRenderParam[3];
parameters[0].type = MpvRenderParamType.ApiType;
parameters[0].data = Marshal.StringToHGlobalAnsi("opengl");
parameters[1].type = MpvRenderParamType.InitParams;
parameters[1].data = oglInitParamsPtr;
parameters[2].type = MpvRenderParamType.Invalid;
parameters[2].data = IntPtr.Zero;
var renderParamSize = Marshal.SizeOf<MpvRenderParam>();
var paramBuf = new byte[renderParamSize * 3];
fixed (byte* paramBufPtr = paramBuf)
{
IntPtr param1Ptr = new IntPtr(paramBufPtr);
Marshal.StructureToPtr(parameters[0], param1Ptr, true);
IntPtr param2Ptr = new IntPtr(paramBufPtr + renderParamSize);
Marshal.StructureToPtr(parameters[1], param2Ptr, true);
IntPtr param3Ptr = new IntPtr(paramBufPtr + renderParamSize + renderParamSize);
Marshal.StructureToPtr(parameters[2], param3Ptr, true);
IntPtr context = new IntPtr(0);
_mpvRenderContextCreate(ref context, _mpvHandle, param1Ptr);
}
}
该函数起作用的原因是:
parameters[0].data = Marshal.StringToHGlobalAnsi("opengl");
而不是使用
parameters[0].data = Marshal.StringToHGlobalAuto("opengl");
我认为这不仅仅是识别使用 opengl 渲染上下文初始化 mpv 播放器所需的“opengl”参数
更新:为了调用该函数,您需要一个初始化的 opengl 上下文,或者,您应该传递 MPV_RENDER_PARAM_OPENGL_INIT_PARAMS 类型的参数以及访问 open gl 函数所需的回调。检查这个 C++ 示例,它使用 SDL 来初始化窗口并获取 opengl 上下文。
https://github.com/mpv-player/mpv-examples/blob/master/libmpv/sdl/main.c
如果没有正确初始化的 OpenGl 上下文,您总是会收到有关正确 c# 编码(marshal)处理的 ViolationException 错误: github.com/mpv-player/mpv/issues/6249
https://github.com/mpv-player/mpv/issues/6507
-- 旧:看看这个: https://stackoverflow.com/questions/20419415/c-sharp-call-c-dll-passing-pointer-to-pointer-argument
关于c# - 调用非托管函数,该函数采用指向指针参数的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59444115/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
指针, C语言的精髓 莫队先咕几天, 容我先讲完树剖 (因为后面树上的东西好多都要用树剖求 LCA). 什么是指针 保存变量地址的变量叫做指针. 这是大概的定义, 但是Defad认为
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我是一名优秀的程序员,十分优秀!