Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid generated delegate AVClass_item_name (returns string instead of byte*) #271

Open
SuRGeoNix opened this issue May 13, 2023 · 3 comments
Labels

Comments

@SuRGeoNix
Copy link

SuRGeoNix commented May 13, 2023

Hi @Ruslan-B,

Got an access violation with this delegate and fixed it by returning byte*. Eg:-

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate byte* AVClass_item_nameX (void* @ctx); // FFmpeg.Autogen bug

public static string? GetProtocolName(AVIOContext* pb)
{
	if (pb == null || pb->av_class == null || pb->av_class->child_next.Pointer == nint.Zero)
		return null;

	var ChildNext = (AVClass_child_next) Marshal.GetDelegateForFunctionPointer(pb->av_class->child_next.Pointer, typeof(AVClass_child_next));
	var child = ChildNext(pb, null);
	var cl = *(AVClass **)child;

	if (cl == null || cl->item_name.Pointer == nint.Zero)
		return null;

	var ItemName = (AVClass_item_nameX) Marshal.GetDelegateForFunctionPointer(cl->item_name.Pointer, typeof(AVClass_item_nameX));

	return Marshal.PtrToStringUTF8((nint)ItemName(child));
}

Might also worth implicit cast from all _func to delegates?

@Ruslan-B
Copy link
Owner

Can I ask for minimal example?

@SuRGeoNix
Copy link
Author

SuRGeoNix commented May 24, 2023

@Ruslan-B Add this function to your 1st example in VideoStreamDecoder.cs

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate byte* AVClass_item_nameX (void* @ctx); // FFmpeg.Autogen bug

public static string? GetProtocolName(AVIOContext* pb)
{
	if (pb == null || pb->av_class == null || pb->av_class->child_next.Pointer ==  IntPtr.Zero)
		return null;

	var ChildNext = (AVClass_child_next) Marshal.GetDelegateForFunctionPointer(pb->av_class->child_next.Pointer, typeof(AVClass_child_next));
	var child = ChildNext(pb, null);
	var cl = *(AVClass **)child;

	if (cl == null || cl->item_name.Pointer == IntPtr.Zero)
		return null;

	var ItemName = (AVClass_item_name) Marshal.GetDelegateForFunctionPointer(cl->item_name.Pointer, typeof(AVClass_item_name));

	return ItemName(child);
	//return Marshal.PtrToStringUTF8((IntPtr)ItemName(child));
}

And add this line to test it after avformat_open_input in the constructor (line 24)

var proto = GetProtocolName(pFormatContext->pb);

You will notice that it will crash at that line with access violation exit code. Then you switch to AVClass_item_nameX instead of AVClass_item_name and use the commented return instead to get the proper result.

var ItemName = (AVClass_item_nameX) Marshal.GetDelegateForFunctionPointer(cl->item_name.Pointer, typeof(AVClass_item_nameX));
...
return Marshal.PtrToStringUTF8((IntPtr)ItemName(child));

@Ruslan-B
Copy link
Owner

Got it. Thanks a lot. I'll look into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants