+
Skip to content

Fix null return of GObject.Value.GetString #813

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

Merged
merged 4 commits into from
Feb 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Generation/Generator/Generator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\GirModel\GirModel.csproj" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
</ItemGroup>
</Project>
6 changes: 3 additions & 3 deletions src/GirCore.Testing.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="FluentAssertions" Version="6.10.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
<PackageReference Include="Moq" Version="4.18.3" />
<PackageReference Include="Moq" Version="4.18.4" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions src/Integration/Integration.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Scriban" Version="5.6.0" IncludeAssets="Build" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" />
<PackageReference Include="Scriban" Version="5.7.0" IncludeAssets="Build" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
</ItemGroup>

<ItemGroup>
Expand Down
12 changes: 12 additions & 0 deletions src/Libs/GLib-2.0/Internal/NullHandleException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace GLib.Internal;

/// <summary>
/// This exception is raised if an unexpeected NULL handle is received. Please report any occurence of this
/// exception to the gir.core project as it is likely to be a generation error.
/// </summary>
public class NullHandleException : Exception
{
public NullHandleException(string message) : base(message) { }
}
31 changes: 30 additions & 1 deletion src/Libs/GLib-2.0/Internal/PlatformStringHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ protected NullablePlatformStringHandle(bool ownsHandle) : base(IntPtr.Zero, owns
[DllImport(ImportResolver.Library, EntryPoint = "g_filename_to_utf8")]
private static extern NonNullableUtf8StringOwnedHandle FilenameToUtf8(IntPtr opsysstring, long len, out nuint bytesRead, out nuint bytesWritten, out ErrorOwnedHandle error);

/// <summary>
/// Converts the data of this handle into a managed string. In case of a NULL
/// pointer this returns null.
/// </summary>
/// <returns>A string containing the handle data or null.</returns>
/// <exception cref="GLib.GException">Thrown if the string could not be converted into utf8.</exception>
public string? ConvertToString()
{
if (IsInvalid)
Expand Down Expand Up @@ -48,6 +54,12 @@ private NullablePlatformStringOwnedHandle() : base(true)
[DllImport(ImportResolver.Library, EntryPoint = "g_filename_from_utf8")]
private static extern IntPtr FilenameFromUtf8(NonNullableUtf8StringHandle utf8string, long len, out nuint bytesRead, out nuint bytesWritten, out ErrorOwnedHandle error);

/// <summary>
/// Creates a nullable platform string handle for the given string.
/// </summary>
/// <param name="s">The string which should be used to create the handle.</param>
/// <returns>A nullable platform string handle</returns>
/// <exception cref="GLib.GException">Thrown if the string could not be converted into a platform string.</exception>
public static NullablePlatformStringOwnedHandle Create(string? s)
{
var handle = new NullablePlatformStringOwnedHandle();
Expand Down Expand Up @@ -75,10 +87,17 @@ protected NonNullablePlatformStringHandle(bool ownsHandle) : base(IntPtr.Zero, o

public override bool IsInvalid => handle == IntPtr.Zero;

/// <summary>
/// Converts the data of this handle into a managed string. In case of a NULL
/// handle this throws a <see cref="GLib.Internal.NullHandleException"/>.
/// </summary>
/// <returns>A string containing the handle data.</returns>
/// <exception cref="GLib.Internal.NullHandleException">Thrown in case of a NULL handle</exception>
/// <exception cref="GLib.GException">Thrown if the string could not be converted into a utf8 string.</exception>
public string ConvertToString()
{
if (IsInvalid)
throw new Exception($"{nameof(NonNullablePlatformStringHandle)} should not have a null handle");
throw new NullHandleException($"{nameof(NonNullablePlatformStringHandle)} should not have a null handle");

NonNullableUtf8StringOwnedHandle result = GLib.Internal.Functions.FilenameToUtf8(this, -1, out _, out _, out var error);
GLib.Error.ThrowOnError(error);
Expand All @@ -98,12 +117,22 @@ protected override bool ReleaseHandle()
}
}

/// <summary>
/// Represents an owned non nullable platform string. If an instance of this class
/// is collected by the garbage collecctor the associated memory is freed.
/// </summary>
public class NonNullablePlatformStringOwnedHandle : NonNullablePlatformStringHandle
{
private NonNullablePlatformStringOwnedHandle() : base(true)
{
}

/// <summary>
/// Creates a non nullable platform string handle for the given string.
/// </summary>
/// <param name="s">The string which should be used to create the handle.</param>
/// <returns>A non nullable utf8 string handle</returns>
/// <exception cref="GLib.GException">Thrown if the string could not be converted into a platform string.</exception>
public static NonNullablePlatformStringOwnedHandle Create(string s)
{
var handle = GLib.Internal.Functions.FilenameFromUtf8(NonNullableUtf8StringOwnedHandle.Create(s), -1, out _, out _, out var error);
Expand Down
31 changes: 30 additions & 1 deletion src/Libs/GLib-2.0/Internal/Utf8StringHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ protected NullableUtf8StringHandle(bool ownsHandle) : base(IntPtr.Zero, ownsHand

public override bool IsInvalid => handle == IntPtr.Zero;

/// <summary>
/// Converts the data of this handle into a managed string. In case of a NULL
/// handle this returns null.
/// </summary>
/// <returns>A string containing the handle data or null.</returns>
public string? ConvertToString()
{
return StringHelper.ToStringUtf8(handle);
Expand All @@ -30,12 +35,21 @@ protected override bool ReleaseHandle()
}
}

/// <summary>
/// Represents an owned nullable utf8 string. If an instance of this class
/// is collected by the garbage collecctor the associated memory is freed.
/// </summary>
public class NullableUtf8StringOwnedHandle : NullableUtf8StringHandle
{
private NullableUtf8StringOwnedHandle() : base(true)
{
}

/// <summary>
/// Creates a nullable utf8 string handle for the given string.
/// </summary>
/// <param name="s">The string which should be used to create the handle.</param>
/// <returns>A nullable utf8 string handle</returns>
public static NullableUtf8StringOwnedHandle Create(string? s)
{
var alloc = new NullableUtf8StringOwnedHandle();
Expand All @@ -58,10 +72,16 @@ protected NonNullableUtf8StringHandle(bool ownsHandle) : base(IntPtr.Zero, ownsH

public override bool IsInvalid => handle == IntPtr.Zero;

/// <summary>
/// Converts the data of this handle into a managed string. In case of a NULL
/// handle this throws a <see cref="GLib.Internal.NullHandleException"/>.
/// </summary>
/// <returns>A string containing the handle data.</returns>
/// <exception cref="GLib.Internal.NullHandleException">Thrown in case of a NULL handle</exception>
public string ConvertToString()
{
if (IsInvalid)
throw new Exception($"{nameof(NonNullableUtf8StringHandle)} should not have a null handle");
throw new NullHandleException($"{nameof(NonNullableUtf8StringHandle)} should not have a null handle");

return StringHelper.ToStringUtf8(handle)!;
}
Expand All @@ -79,12 +99,21 @@ protected override bool ReleaseHandle()
}
}

/// <summary>
/// Represents an owned non nullable utf8 string. If an instance of this class
/// is collected by the garbage collecctor the associated memory is freed.
/// </summary>
public class NonNullableUtf8StringOwnedHandle : NonNullableUtf8StringHandle
{
private NonNullableUtf8StringOwnedHandle() : base(true)
{
}

/// <summary>
/// Creates a non nullable utf8 string handle for the given string.
/// </summary>
/// <param name="s">The string which should be used to create the handle.</param>
/// <returns>A non nullable utf8 string handle</returns>
public static NonNullableUtf8StringOwnedHandle Create(string s)
{
var alloc = new NonNullableUtf8StringOwnedHandle();
Expand Down
10 changes: 8 additions & 2 deletions src/Libs/GObject-2.0/Public/Value.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public ParamSpec GetParam()
public float GetFloat() => Internal.Value.GetFloat(Handle);
public ulong GetFlags() => Internal.Value.GetFlags(Handle);
public long GetEnum() => Internal.Value.GetEnum(Handle);
public string GetString() => Internal.Value.GetString(Handle).ConvertToString();
public string? GetString() => GetString(Handle).ConvertToString();
public GLib.Variant? GetVariant()
{
var result = Internal.Value.GetVariant(Handle);
Expand Down Expand Up @@ -242,8 +242,14 @@ public void Dispose()
// avoid the GObject.Internal.Value.Handle creation this method
// returns just an IntPtr. It is okay to return an IntPtr as the
// returned IntPtr points to the location of the "value" parameter.
[DllImport("GObject", EntryPoint = "g_value_init")]
[DllImport(ImportResolver.Library, EntryPoint = "g_value_init")]
private static extern IntPtr Init(GObject.Internal.ValueHandle value, nuint gType);

//TODO: g_value_get_string get's redeclared here as it is not annotated correctly.
//Remove after release of: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3301
//Use "Internal.Value.GetString(Handle).ConvertToString();" again
[DllImport(ImportResolver.Library, EntryPoint = "g_value_get_string")]
public static extern GLib.Internal.NullableUtf8StringUnownedHandle GetString(GObject.Internal.ValueHandle value);

#endregion
}
97 changes: 97 additions & 0 deletions src/Native/GirTestLib/girtest-property-tester.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include "girtest-property-tester.h"

/**
* GirTestPropertyTester:
*
* Contains properties to test bindings.
*/

typedef enum
{
PROP_STRING_VALUE = 1,
N_PROPERTIES
} PropertyTesterProperty;

struct _GirTestPropertyTester
{
GObject parent_instance;

gchar *string_value;
};

G_DEFINE_TYPE(GirTestPropertyTester, girtest_property_tester, G_TYPE_OBJECT)

static GParamSpec *properties[N_PROPERTIES];


static void
girtest_property_tester_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GirTestPropertyTester *self = GIRTEST_PROPERTY_TESTER (object);

switch (prop_id)
{
case PROP_STRING_VALUE:
g_value_set_string (value, self->string_value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}

static void
girtest_property_tester_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GirTestPropertyTester *self = GIRTEST_PROPERTY_TESTER (object);

switch (prop_id)
{
case PROP_STRING_VALUE:
self->string_value = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}

static void
girtest_property_tester_init(GirTestPropertyTester *value)
{
}

static void
girtest_property_tester_class_init(GirTestPropertyTesterClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);

object_class->set_property = girtest_property_tester_set_property;
object_class->get_property = girtest_property_tester_get_property;

properties[PROP_STRING_VALUE] =
g_param_spec_string ("string-value",
"String Value",
"A string value",
NULL /* default value */,
G_PARAM_READWRITE);

g_object_class_install_properties (object_class, N_PROPERTIES, properties);
}

/**
* girtest_property_tester_new:
*
* Creates a new `GirTestPropertyTester`.
*
* Returns: The newly created `GirTestPropertyTester`.
*/
GirTestPropertyTester*
girtest_property_tester_new (void)
{
return g_object_new (GIRTEST_TYPE_PROPERTY_TESTER, NULL);
}
16 changes: 16 additions & 0 deletions src/Native/GirTestLib/girtest-property-tester.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <glib-object.h>

G_BEGIN_DECLS

#define GIRTEST_TYPE_PROPERTY_TESTER girtest_property_tester_get_type()

G_DECLARE_FINAL_TYPE(GirTestPropertyTester, girtest_property_tester,
GIRTEST, PROPERTY_TESTER, GObject)

GirTestPropertyTester*
girtest_property_tester_new (void);

G_END_DECLS

26 changes: 26 additions & 0 deletions src/Native/GirTestLib/girtest-string-tester.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,30 @@ girtest_string_tester_callback_return_string_transfer_full (GirTestReturnStringF
destroy(user_data);

return len;
}

/**
* girtest_string_tester_utf8_return_unexpected_null:
*
* Returns null but is missing the annotation.
*
* Returns: NULL
*/
gchar *
girtest_string_tester_utf8_return_unexpected_null()
{
return NULL;
}

/**
* girtest_string_tester_filename_return_unexpected_null:
*
* Returns null but is missing the annotation.
*
* Returns: (type filename): NULL
*/
gchar *
girtest_string_tester_filename_return_unexpected_null()
{
return NULL;
}
6 changes: 6 additions & 0 deletions src/Native/GirTestLib/girtest-string-tester.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,11 @@ girtest_string_tester_filename_return_nullable_transfer_none(const gchar *s);
int
girtest_string_tester_callback_return_string_transfer_full(GirTestReturnStringFunc callback, gpointer user_data, GDestroyNotify destroy);

gchar *
girtest_string_tester_utf8_return_unexpected_null();

gchar *
girtest_string_tester_filename_return_unexpected_null();

G_END_DECLS

1 change: 1 addition & 0 deletions src/Native/GirTestLib/girtest.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
#include "girtest-class-tester.h"
#include "girtest-error-tester.h"
#include "girtest-primitive-value-type-tester.h"
#include "girtest-property-tester.h"
#include "girtest-returning-signal-tester.h"
#include "girtest-string-tester.h"
2 changes: 2 additions & 0 deletions src/Native/GirTestLib/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ header_files = [
'girtest-class-tester.h',
'girtest-error-tester.h',
'girtest-primitive-value-type-tester.h',
'girtest-property-tester.h',
'girtest-returning-signal-tester.h',
'girtest-string-tester.h',
]
Expand All @@ -15,6 +16,7 @@ source_files = [
'girtest-class-tester.c',
'girtest-error-tester.c',
'girtest-primitive-value-type-tester.c',
'girtest-property-tester.c',
'girtest-returning-signal-tester.c',
'girtest-string-tester.c',
]
Expand Down
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载