C#:从libnotify C struct获取值
我正试图从我的c#代码中访问c libnotify,以便在带有dotnet内核的linux笔记本电脑上使用libnotifyC#:从libnotify C struct获取值,c#,.net,.net-core,libnotify,C#,.net,.net Core,Libnotify,我正试图从我的c#代码中访问c libnotify,以便在带有dotnet内核的linux笔记本电脑上使用libnotify 但每次从库中获取值都会出现问题 这是有问题的c代码: typedef struct _NotifyNotification NotifyNotification; typedef struct _NotifyNotificationPrivate NotifyNotificationPrivate; struct _NotifyNotification { /*
但每次从库中获取值都会出现问题 这是有问题的c代码:
typedef struct _NotifyNotification NotifyNotification;
typedef struct _NotifyNotificationPrivate NotifyNotificationPrivate;
struct _NotifyNotification
{
/*< private >*/
GObject parent_object;
NotifyNotificationPrivate *priv;
};
struct _NotifyNotificationPrivate
{
guint32 id;
char *app_name;
char *summary;
char *body;
/* NULL to use icon data. Anything else to have server lookup icon */
char *icon_name;
/*
* -1 = use server default
* 0 = never timeout
* > 0 = Number of milliseconds before we timeout
*/
gint timeout;
GSList *actions;
GHashTable *action_map;
GHashTable *hints;
gboolean has_nondefault_actions;
gboolean updates_pending;
gulong proxy_signal_handler;
gint closed_reason;
};
NotifyNotification *
notify_notification_new (const char *summary,
const char *body,
const char *icon);
使用此代码,我将所有内容强制转换为结构:
NotifyNotification no = (NotifyNotification) Marshal.PtrToStructure(not, typeof(NotifyNotification));
Console.WriteLine(Marshal.PtrToStringAnsi(no.priv.summary));
基本功能正常,我可以使用notify_notification_new-method中的指针从libnotify调用其他函数。
但在最后一行,在WriteLine中,调试器说:
The program '...dll' has exited with code 0 (0x00000000).
没有例外,也没有错误。出什么事了?这是dotnetcore的问题吗?因为它还在测试阶段
如何从属性应用程序获取文本?名称、摘要、正文
非常感谢您的帮助。[StructLayout(LayoutKind.Explicit)]
说:“亲爱的编译器,我知道我在做什么,只是……处理一下。”。不幸的是,你不知道自己在做什么<代码>[FieldOffset]以字节为单位获取偏移量,而不是以成员为单位
struct _NotifyNotification
{
/*< private >*/
GObject parent_object;
NotifyNotificationPrivate *priv;
};
你读
id = [01 02 03 04] => 0x04030201 (because Little-Endian)
app_name = [02 03 04 05 06 07 08 09] => 0x0908070605040302
summary = [03 04 05 06 07 08 09 0A] => 0x0A09080706050403
timeout = [06 07 08 09] => 0x09080706
最好使用顺序布局:
[StructLayout(LayoutKind.Sequential)]
internal struct NotifyNotification
{
private IntPtr parent_object;
public IntPtr priv;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NotifyNotificationPrivate
{
public uint id;
public IntPtr app_name;
public IntPtr summary;
private IntPtr body;
private IntPtr icon_name;
public int timeout;
// If you're only ever reading one of these structures
// you can skip the rest. If you ever allocate one, be sure to
// include all of the fields so the right amount of memory is created
}
然后:
<> > > >编辑:,最可预测的方法是创建C库(或C++,带有<代码>外部)C“< /COD>声明”,避免了复制/解释结构(它让C编译器负责):
与之匹配的C#声明是将函数声明为返回
IntPtr
,并将其仍传递给Marshal.PtrToStringAnsi
;因为如果你声明它返回一个字符串
,GC会认为它应该在字符串超出范围时清理内存。好的,谢谢你的回答。这是有道理的。但是:在将NotifyNotification指针编组到NotifyNotification结构之后,priv的值为:0x0000000000000001。因此,我无法将其封送到NotifyNotificationPrivate结构。为什么?这应该是另一个值,不是吗?@bittnerd啊,因为GObject是一个结构,而不是指针。最好的办法是制作一个小型C库,您可以将NotifyNotification*
传入,然后将NotifyNotificationPrivate*
传出。这样,C编译器就可以进行字段偏移量计算,并且您不需要在GNOME框架的不同版本中尝试改变GObject的结构。谢谢您的帮助。事实上,我不想用额外的图书馆这样做。但我认为这是最好的方法,我不知道还有其他方法可以得到这些值。如果您将该评论添加到您的答案中,我将接受。:)@完成了。填充(一切)是在Linux上的CoreFx中完成的方法,结构布局是最初的激励因素。(特别是对于允许有条件地编译字段的库)
id = [01 02 03 04] => 0x04030201 (because Little-Endian)
app_name = [02 03 04 05 06 07 08 09] => 0x0908070605040302
summary = [03 04 05 06 07 08 09 0A] => 0x0A09080706050403
timeout = [06 07 08 09] => 0x09080706
[StructLayout(LayoutKind.Sequential)]
internal struct NotifyNotification
{
private IntPtr parent_object;
public IntPtr priv;
}
[StructLayout(LayoutKind.Sequential)]
internal struct NotifyNotificationPrivate
{
public uint id;
public IntPtr app_name;
public IntPtr summary;
private IntPtr body;
private IntPtr icon_name;
public int timeout;
// If you're only ever reading one of these structures
// you can skip the rest. If you ever allocate one, be sure to
// include all of the fields so the right amount of memory is created
}
NotifyNotification no = (NotifyNotification) Marshal.PtrToStructure(not, typeof(NotifyNotification));
NotifyNotificationPrivate noPriv = (NotifyNotificationPrivate) Marshal.PtrToStructure(no.priv, typeof(NotifyNotificationPrivate));
Console.WriteLine(Marshal.PtrToStringAnsi(noPriv.summary));
extern "C" char* ReadNotificationSummary(NotifyNotification* notification)
{
if (notification == nullptr || notification.priv == nullptr)
return nullptr;
return notification.priv->summary;
}