для справки, в конце этого сообщения вы найдете то, что я понял из протокола, чтобы поговорить с плагином Gimp. 3 вещи < /p>
[*] Используйте CreatePipe из kernel32, затем iochannel.fromhandle
// сбои с системой. />
// Не удается после
Некоторые секунды с (0xc0000409) < /p>
< /li>
Использовать _pipe из msvcrt.dll then _get_osfhandle (fd [0]) затем
ikannel.fromhandle(radehandle); /> system.accessviolationException
< /li>
< /ul>
Последние два «лучше», потому что они используют _pipe, которая возвращает дескриптор файла int, который мне нужен, когда первые возвращают intptr.
Код: Выделить всё
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using GLib;
class PipeTalker
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe,
IntPtr lpPipeAttributes, uint nSize);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern int _pipe(out IntPtr filedes, uint size, int textmode);
// For _pipe, you pass an int array of 2 elements. This signature adapted accordingly:
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern int _pipe(int[] pfds, uint size, int textmode);
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern IntPtr _get_osfhandle(int fd);
const int _O_BINARY = 0x8000; // 0x0200 0x8000 ?
private IOChannel ioRead;
private IOChannel ioWrite;
private bool GioIn(IOChannel source, IOCondition condition)
{
if ((condition & IOCondition.Hup) == IOCondition.Hup)
{
Console.WriteLine("Read end of pipe closed.");
return false; // Arrêter le watch
}
try
{
source.ReadLine(out string line, out ulong length);
if (line != null)
{
Console.WriteLine($"Received ({length} bytes): {line}");
}
}
catch (Exception e)
{
Console.WriteLine("Error reading from pipe: " + e.Message);
return false;
}
return true; // Continuer le watch
}
private bool GioOut(IOChannel source, IOCondition condition)
{
if ((condition & IOCondition.Hup) == IOCondition.Hup)
{
Console.WriteLine("Write end of pipe closed.");
return false;
}
string message = "The price of greatness is responsibility.\n";
try
{
source.WriteChars(Encoding.ASCII.GetBytes(message), out ulong length);
source.Flush();
Console.WriteLine($"Sent {length} bytes.");
}
catch (Exception e)
{
Console.WriteLine("Error writing to pipe: " + e.Message);
return false;
}
return false;
}
public void InitChannels()
{
bool success = CreatePipe(out IntPtr readHandle, out IntPtr writeHandle, IntPtr.Zero, 4096);
if (!success)
{
Console.WriteLine("Failed to create pipe. Error code: " + Marshal.GetLastWin32Error());
return;
}
ioRead = IOChannel.FromHandle(readHandle); // FAILS with System.AccessViolationException
ioWrite = IOChannel.FromHandle(writeHandle);
// alternative. Fails too
int[] fd = new int[2]; // file descriptor
int ret;
// setup a pipe
// was ret = Posix.pipe(fd);
ret = _pipe(fd, 4096, _O_BINARY);
if (ret == -1)
{
Console.Write("Creating pipe failed: \n"); // use IOChannel.ErrorFromErrno ?
return;
}
ioRead = new IOChannel(fd[0]); // FAILS after some seconds with (0xc0000409)
// other alternative
readHandle = _get_osfhandle(fd[0]);
ioRead = IOChannel.FromHandle(readHandle); // FAILS with System.AccessViolationException
if (ioRead == null || ioWrite == null)
{
Console.WriteLine("Failed to create IOChannels.");
return;
}
// Ajouter watcher pour lecture (IN | HUP)
ioRead.AddWatch(0,IOCondition.In | IOCondition.Hup, GioIn);
// Ajouter watcher pour écriture (OUT | HUP)
ioWrite.AddWatch(0,IOCondition.Out | IOCondition.Hup, GioOut);
}
static void Main()
{
string gtklibs = @"C:\gtk\bin"; //
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? "";
if (!currentPath.Split(';').Contains(gtklibs))
{
Environment.SetEnvironmentVariable("PATH", gtklibs + ";" + currentPath);
}
GLib.ExceptionManager.UnhandledException += (sender) =>
{
;
Exception e = (Exception)sender.ExceptionObject;
Console.WriteLine("GLib Unhandled Exception: " + e.Message);
sender.ExitApplication = true;
};
var pt = new PipeTalker();
pt.InitChannels();
Console.WriteLine("Starting GLib MainLoop...");
var loop = new MainLoop();
loop.Run();
Console.WriteLine("MainLoop exited, cleaning up.");
// free handles
if (pt.ioRead != null)
CloseHandle(pt.ioRead.Handle);
if (pt.ioWrite != null)
CloseHandle(pt.ioWrite.Handle);
}
}
< /code>
Программа собирается с использованием Visual Studio в качестве «любого ЦП» без «предпочтения 32 бита».
Глиб ссылается через NUGET. < /p>
==== />Open pipe;
[*]Fork the program;
[*]run '"C:\Program Files\GIMP 3\lib\gimp\3.0\plug-ins\fractal-explorer\fractal-explorer.exe" -gimp 277 5 4 -query 0' as the child
ping/pong text in the трубы.ARG_PROGNAME, // self explaining
ARG_GIMP, // string "-gimp"
ARG_PROTOCOL_VERSION, // 277 looks strange but will pass it anyways
ARG_READ_FD, // int that maps the file descriptor for reading; here 5
ARG_WRITE_FD, // int that maps the file descriptor for reading; here 4
ARG_MODE, // string '-run', '-query','-init'
ARG_STACK_TRACE_MODE, // debug mode 0 = no debug
см. https://gitlab.gnome.org/gnome/gimp/-/b ... imp/gimp.c строка 440
Код: Выделить всё
...
read_channel = g_io_channel_win32_new_fd (atoi (argv[ARG_READ_FD]));
write_channel = g_io_channel_win32_new_fd (atoi (argv[ARG_WRITE_FD]));
...
Подробнее здесь: https://stackoverflow.com/questions/797 ... -from-them
Мобильная версия