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

GraphABCHelper: Приведение типа указателя к integer (int32) вместо Int64 вызывает Exception в Linux #2801

Open
softexe opened this issue Feb 8, 2023 · 16 comments

Comments

@softexe
Copy link

softexe commented Feb 8, 2023

Ниже приведены изменения, которые устраняют данный Exception под Linux и работает под Windows

iptr1,iptr2: integer;

iptr1,iptr2: int64;

iptr1 := integer(ptr1);

iptr1 := int64(ptr1);

iptr2 := integer(ptr2);

iptr2 := int64(ptr2);

@softexe softexe changed the title Приведение типа указателя к integer (int32) вместо Int64 вызывает Exception в Linux GraphABCHelper Приведение типа указателя к integer (int32) вместо Int64 вызывает Exception в Linux Feb 8, 2023
@softexe softexe changed the title GraphABCHelper Приведение типа указателя к integer (int32) вместо Int64 вызывает Exception в Linux GraphABCHelper: Приведение типа указателя к integer (int32) вместо Int64 вызывает Exception в Linux Feb 8, 2023
@SunSerega
Copy link
Contributor

Exception значит исключение. Какое исключение то? Конкретный тип нужен. И текст ошибки тоже не для красоты выводится.

@softexe
Copy link
Author

softexe commented Feb 8, 2023

Exception значит исключение. Какое исключение то? Конкретный тип нужен. И текст ошибки тоже не для красоты выводится.

Посмотрите, может поможет.


================================================================
	Native Crash Reporting
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

=================================================================
	Native stacktrace:
=================================================================
	0x56322119fdab - /usr/bin/mono : 
	0x5632211a0169 - /usr/bin/mono : 
	0x56322114713f - /usr/bin/mono : 
	0x5632211990f8 - /usr/bin/mono : 
	0x7fde6ec0dce6 - /usr/lib64/libpixman-1.so.0 : 
	0x7fde6eba548d - /usr/lib64/libpixman-1.so.0 : pixman_image_composite32
	0x7fde6ef768cd - /usr/lib64/libcairo.so.2 : 
	0x7fde6efae52f - /usr/lib64/libcairo.so.2 : 
	0x7fde6efaeccc - /usr/lib64/libcairo.so.2 : 
	0x7fde6ef6a511 - /usr/lib64/libcairo.so.2 : 
	0x7fde6efbb508 - /usr/lib64/libcairo.so.2 : 
	0x7fde6ef72846 - /usr/lib64/libcairo.so.2 : 
	0x7fde6efc91aa - /usr/lib64/libcairo.so.2 : cairo_paint
	0x7fde6f1dcc10 - /usr/lib64/libgdiplus.so.0 : GdipDrawImageRect
	0x41f53608 - Unknown

=================================================================

@SunSerega
Copy link
Contributor

SunSerega commented Feb 8, 2023

Нуок, только теперь не понятно где вы нашли исключение - я вижу только краш среды выполнения .Net (среды от mono в данном случае)
Но по хорошему, тут ни integer, ни к int64, ни к pointer приводить не надо. Надо выполнять арифметические операции над IntPtr напрямую - этот тип как раз представляет число с длиной, равно размеру указателя (4/8 байт в зависимости от битности системы)

@softexe
Copy link
Author

softexe commented Feb 9, 2023

адо выполнять арифметические операции над IntPtr напрямую - этот тип как раз представляет число с длиной, равно размеру указателя (4/8 байт в зависимости от битности системы)

не понятно, почему изначально использовался integer вместо IntPtr, и не только в этой функции. Будем править?

@SunSerega
Copy link
Contributor

SunSerega commented Feb 9, 2023

Не только тут, мне кажется изначально многое делалось без расчёта на 64-битные системы.
А с тем как работает винда - даже на 64-битных это обычно не заметно. А вы поймали потому что на линуксе запустили.

Вот пример получше:
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox
А в справке единственный пример external:

function MessageBox(h: integer; m,c: string; t: integer): integer; 
  external 'User32.dll' name 'MessageBox'; 

h тут дескриптор окна, он тоже должен быть IntPtr.

Что касается тут - я лично считаю что мне лучше вложить усилия во что то типа OpenGLABC. На это надо на много больше времени, но зато результат будет лучше, чем пытаться исправить легаси модуль потому что пока что нет ничего лучше.
Но если это изменения что нужны вам - смотрите как я сделал:

У меня есть своя ветка в форке, со своим батником для билда.
Когда мне нужно что-то подправить - я создаю ещё 1 ветку из мастера, делаю там исправление, и мерджу это исправление в ветку custom-build. В то же время, использую ту временную ветку чтобы послать пулл в этот репозиторий.
Таким образом я посылаю сюда эти исправления, чтобы они не только у меня были. Но в то же время в custom-build находится весь зоопарк из того, что её не приняли, а мне нужно (правда прямо сейчас таких нет).

P.S. Забыл сказать, в том батнике 0_official и SunSerega это remote-ы, то есть репозитории: Данная репа и мой форк соответственно.
Я добавил их оба в свой локальный клон, чтобы можно было простым образом выполнять операции между ветками оригинала и форка.

@miks1965
Copy link
Contributor

Не только тут, мне кажется изначально многое делалось без расчёта на 64-битные системы.

Так и есть. Исправим на int64 - и на старых 32 разрядных системах всё перестанет работать.

Есть другие варианты исправления?

@softexe
Copy link
Author

softexe commented Feb 14, 2023

Тогда использовать предопределенные для платформы типы IntPtr и HWND

@SunSerega
Copy link
Contributor

Исправим на int64 - и на старых 32 разрядных системах всё перестанет работать.

С чего вдруг? На 32-битных компах будет медленнее, но сломаться от этого ничего не может.
Но таки да, надо IntPtr использовать. Я вообще не понимаю почему вы его дискриминируете, хотя это такой же цело-численный тип как integer и int64.

@miks1965
Copy link
Contributor

Нет, сделайте исправление и оттестируйте - я это прошу.

Вы уже переключились - а мне - переключаться и вникать.

К тому же - я не пойму - после этой правки будет работать ABCObjects в Linux или нет?

@softexe
Copy link
Author

softexe commented Feb 14, 2023

К тому же - я не пойму - после этой правки будет работать ABCObjects в Linux или нет?

еще раз -- надо GetView другую.
А тест на 32 бит и виндовс и линукс?

@miks1965
Copy link
Contributor

miks1965 commented Feb 14, 2023

Конечно крайне жедательно чтобы GetView была общей для win и Linux. Но если не бедет получаться, то можно разные

@softexe
Copy link
Author

softexe commented Feb 14, 2023

Конечно крайне жедательно чтобы GetView была общей для win и Linux. Но если не бедет получаться, то можно разные

измененная работает на обеих платформах.

@miks1965
Copy link
Contributor

miks1965 commented Mar 7, 2023

Давайте подведем итог.

Новый GetView будет или мне просто поменять на int64 и закрыть issue?

@softexe
Copy link
Author

softexe commented Mar 7, 2023

Давайте подведем итог.

Новый GetView будет или мне просто поменять на int64 и закрыть issue?

Вроде готовил ответ, но видимо не отправил....
Обе функции проверены и работают на Вин 7/10 32/64 бит, Linux 64bit.

В ImageIntersect используется системноопределяемый тип IntPtr.


function GetView(b: Bitmap; r: System.Drawing.Rectangle): Bitmap;  
begin
  var rect := new System.Drawing.Rectangle(0,0,b.Width,b.Height);
  r := System.Drawing.Rectangle.Intersect(r,rect);
  result := b.Clone(r, b.PixelFormat);
end;

function ImageIntersect(b1,b2: Bitmap): boolean;
// Предполагается, что b1 и b2 - одного размера
type 
  RGB = record
    r,g,b: byte;
  end;
  PRGB = ^uint32;

label 1;
var
  ptr1,ptr2: IntPtr;
  p1,p2: PRGB;
  rect: System.Drawing.Rectangle;
  bmpData1,bmpData2: System.Drawing.Imaging.BitmapData;
begin
  rect := new System.Drawing.Rectangle(0,0,b1.Width,b1.Height);
  bmpData1 := b1.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, b1.PixelFormat);
  ptr1 := bmpData1.Scan0;
  bmpData2 := b2.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, b2.PixelFormat);
  ptr2 := bmpData2.Scan0;
  var pixelFormatSize := Image.GetPixelFormatSize(b1.PixelFormat) div 8;
  var Offset := bmpData1.stride - b1.Width * pixelFormatSize; 
  Result := False;
  for var y:=0 to b1.Height-1 do
  begin
    for var x:=0 to b1.Width-1 do
    begin
      p1 := PRGB(pointer(ptr1));
      p2 := PRGB(pointer(ptr2));
      //writeln(p1^.R,' ',p1^.G,' ',p1^.B,'  ',p2^.R,' ',p2^.G,' ',p2^.B);
//      if ((p1^.R and p1^.G and p1^.B)<>$FF) and ((p2^.R and p2^.G and p2^.B)<>$FF) then
      if (p1^<>$FFFFFFFF) and (p2^<>$FFFFFFFF) then
      begin
        Result := True;
        goto 1;
      end;
      ptr1 := ptr1 + pixelFormatSize;
      ptr2 := ptr2 + pixelFormatSize;
    end;
    ptr1 := ptr1 + Offset;
    ptr2 := ptr2 + Offset;
  end;
1:  
  b2.UnlockBits(bmpData2);
  b1.UnlockBits(bmpData1);
end; 
  

@miks1965
Copy link
Contributor

miks1965 commented Mar 7, 2023

Ну то есть, можно заменить эти две функции и всё будет работать?

@softexe
Copy link
Author

softexe commented Mar 8, 2023

Ну то есть, можно заменить эти две функции и всё будет работать?

всё так

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

No branches or pull requests

3 participants