Проблемы с pinvoke
От: Visor2004  
Дата: 05.01.12 14:54
Оценка:
дано: две простенькие программы, обе вызывают CreateWindowEx, в случае с C# все отрабатывает как часы, в случае Nemerle функция возвращает ошибку System can not find the file specified. Свойства обоих проектов — by default, т.е. any cpu и там и там, винда x64 семерка.
вопрос: равнозначны ли след. листинги и если да, то в чем проблема?


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace test2
{
    class Program
    {
        static void Main(string[] args)
        {
            CreateWindowEx(0, "STATIC", "asdjflaskdfh", WindowStyles.WS_OVERLAPPEDWINDOW,
                1, 1, 300, 300, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
            var code = Marshal.GetLastWin32Error();
            if (code != 0)
                throw new Win32Exception(code);
        }

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr CreateWindowEx(
           WindowStylesEx dwExStyle,
           string lpClassName,
           string lpWindowName,
           WindowStyles dwStyle,
           int x,
           int y,
           int nWidth,
           int nHeight,
           IntPtr hWndParent,
           IntPtr hMenu,
           IntPtr hInstance,
           IntPtr lpParam);
    }
    [Flags()]
    enum WindowStyles : uint
    {
        WS_BORDER = 0x800000,
        WS_CAPTION = 0xc00000,
        WS_CHILD = 0x40000000,
        WS_CLIPCHILDREN = 0x2000000,
        WS_CLIPSIBLINGS = 0x4000000,
        WS_DISABLED = 0x8000000,
        WS_DLGFRAME = 0x400000,
        WS_GROUP = 0x20000,
        WS_HSCROLL = 0x100000,
        WS_MAXIMIZE = 0x1000000,
        WS_MAXIMIZEBOX = 0x10000,
        WS_MINIMIZE = 0x20000000,
        WS_MINIMIZEBOX = 0x20000,
        WS_OVERLAPPED = 0x0,
        WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_SIZEFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
        WS_POPUP = 0x80000000u,
        WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
        WS_SIZEFRAME = 0x40000,
        WS_SYSMENU = 0x80000,
        WS_TABSTOP = 0x10000,
        WS_VISIBLE = 0x10000000,
        WS_VSCROLL = 0x200000
    }

    [Flags]
    enum WindowStylesEx : uint
    {
        WS_EX_ACCEPTFILES = 0x00000010,
        WS_EX_APPWINDOW = 0x00040000,
        WS_EX_CLIENTEDGE = 0x00000200,
        WS_EX_COMPOSITED = 0x02000000,
        WS_EX_CONTEXTHELP = 0x00000400,
        WS_EX_CONTROLPARENT = 0x00010000,
        WS_EX_DLGMODALFRAME = 0x00000001,
        WS_EX_LAYERED = 0x00080000,
        WS_EX_LAYOUTRTL = 0x00400000,
        WS_EX_LEFT = 0x00000000,
        WS_EX_LEFTSCROLLBAR = 0x00004000,
        WS_EX_LTRREADING = 0x00000000,
        WS_EX_MDICHILD = 0x00000040,
        WS_EX_NOACTIVATE = 0x08000000,
        WS_EX_NOINHERITLAYOUT = 0x00100000,
        WS_EX_NOPARENTNOTIFY = 0x00000004,
        WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
        WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
        WS_EX_RIGHT = 0x00001000,
        WS_EX_RIGHTSCROLLBAR = 0x00000000,
        WS_EX_RTLREADING = 0x00002000,
        WS_EX_STATICEDGE = 0x00020000,
        WS_EX_TOOLWINDOW = 0x00000080,
        WS_EX_TOPMOST = 0x00000008,
        WS_EX_TRANSPARENT = 0x00000020,
        WS_EX_WINDOWEDGE = 0x00000100
    }
}



using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Console;
using System.Linq;
using System.Runtime.InteropServices;
using System.ComponentModel;

module Program
{
  Main() : void
  {
    _ = CreateWindowEx(0, "STATIC", "asdjflaskdfh", WindowStyles.WS_OVERLAPPEDWINDOW,
                       1, 1, 300, 300, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
    def code = Marshal.GetLastWin32Error();
    when (code != 0)
      throw Win32Exception(code);
  }

  [DllImportAttribute ( "User32.dll", SetLastError=true )]
  extern CreateWindowEx(dwExStyle : WindowStylesEx, lpClassName : string, lpWindowName : string, dwStyle : WindowStyles, 
      x : int, y : int, nWidth : int, nHeight : int, hWndParent : IntPtr, hMenu : IntPtr, hInstance : IntPtr, lpParam : IntPtr) : IntPtr;

  [FlagsAttribute]
  enum WindowStyles : uint
  {
    | WS_BORDER = 0x800000
    | WS_CAPTION = 0xc00000
    | WS_CHILD = 0x40000000
    | WS_CLIPCHILDREN = 0x2000000
    | WS_CLIPSIBLINGS = 0x4000000
    | WS_DISABLED = 0x8000000
    | WS_DLGFRAME = 0x400000
    | WS_GROUP = 0x20000
    | WS_HSCROLL = 0x100000
    | WS_MAXIMIZE = 0x1000000
    | WS_MAXIMIZEBOX = 0x10000
    | WS_MINIMIZE = 0x20000000
    | WS_MINIMIZEBOX = 0x20000
    | WS_OVERLAPPED = 0x0
    | WS_OVERLAPPEDWINDOW = 0xCF0000
    | WS_POPUP = 0x80000000u
    | WS_POPUPWINDOW = 0x80880000
    | WS_SIZEFRAME = 0x40000
    | WS_SYSMENU = 0x80000
    | WS_TABSTOP = 0x10000
    | WS_VISIBLE = 0x10000000
    | WS_VSCROLL = 0x200000
  }

  [FlagsAttribute]     
  enum WindowStylesEx : uint 
  {
    | WS_EX_ACCEPTFILES = 0x00000010
    | WS_EX_APPWINDOW = 0x00040000
    | WS_EX_CLIENTEDGE = 0x00000200
    | WS_EX_COMPOSITED = 0x02000000
    | WS_EX_CONTEXTHELP = 0x00000400
    | WS_EX_CONTROLPARENT = 0x00010000
    | WS_EX_DLGMODALFRAME = 0x00000001
    | WS_EX_LAYERED = 0x00080000
    | WS_EX_LAYOUTRTL = 0x00400000
    | WS_EX_LEFT = 0x00000000
    | WS_EX_LEFTSCROLLBAR = 0x00004000
    | WS_EX_LTRREADING = 0x00000000
    | WS_EX_MDICHILD = 0x00000040
    | WS_EX_NOACTIVATE = 0x08000000
    | WS_EX_NOINHERITLAYOUT = 0x00100000
    | WS_EX_NOPARENTNOTIFY = 0x00000004
    | WS_EX_OVERLAPPEDWINDOW = 0x00000300
    | WS_EX_PALETTEWINDOW = 0x00000188
    | WS_EX_RIGHT = 0x00001000
    | WS_EX_RIGHTSCROLLBAR = 0x00000000
    | WS_EX_RTLREADING = 0x00002000
    | WS_EX_STATICEDGE = 0x00020000
    | WS_EX_TOOLWINDOW = 0x00000080
    | WS_EX_TOPMOST = 0x00000008
    | WS_EX_TRANSPARENT = 0x00000020
    | WS_EX_WINDOWEDGE = 0x00000100
  }
}
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re: Проблемы с pinvoke
От: _NN_ www.nemerleweb.com
Дата: 05.01.12 15:27
Оценка: 6 (1)
Здравствуйте, Visor2004, Вы писали:

V>дано: две простенькие программы, обе вызывают CreateWindowEx, в случае с C# все отрабатывает как часы, в случае Nemerle функция возвращает ошибку System can not find the file specified. Свойства обоих проектов — by default, т.е. any cpu и там и там, винда x64 семерка.

V>вопрос: равнозначны ли след. листинги и если да, то в чем проблема?

В том и дело что нет.

У Nemerle имеется баг. Игнорируется SetLastError=true !

module Program
{
  [DllImport("a.dll", SetLastError=true)]
  public extern F() : void;
}



ILSpy:
class Program
{
  [DllImport("a.dll")]
  public static extern void F();
}


Тест:
using System;
using System.Console;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Reflection;

namespace test2
{
    module Program
    {
      [DllImport("a.dll", SetLastError=true)]
      public extern F() : void;
      
      Main() : void
      {          
        def t = Type.GetType("test2.Program");
        def f = t.GetMethod("F");
        
        foreach (at in f.GetCustomAttributes(false))
        {
          | dat is DllImportAttribute => WriteLine(dat.SetLastError);
          | _ => ()
        }
      }
   }
}

False

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Проблемы с pinvoke
От: Visor2004  
Дата: 05.01.12 15:29
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>У Nemerle имеется баг. Игнорируется SetLastError=true !


пофиг на баг, если бы окно реально создавалось, я бы даже не думал смотреть GetLastError
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re[3]: Проблемы с pinvoke
От: _NN_ www.nemerleweb.com
Дата: 05.01.12 15:33
Оценка:
Здравствуйте, Visor2004, Вы писали:

V>Здравствуйте, _NN_, Вы писали:


_NN>>У Nemerle имеется баг. Игнорируется SetLastError=true !


V>пофиг на баг, если бы окно реально создавалось, я бы даже не думал смотреть GetLastError


А как вы проверяете что оно создается ?

Код падает в "when (code != 0) throw Win32Exception(code);", т.к. LastError не устанавливается в 0 из-за SetLastError = false.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Проблемы с pinvoke
От: Visor2004  
Дата: 05.01.12 15:39
Оценка:
Здравствуйте, _NN_, Вы писали:
_NN>А как вы проверяете что оно создается ?

_NN>Код падает в "when (code != 0) throw Win32Exception(code);", т.к. LastError не устанавливается в 0 из-за SetLastError = false.


ну, например, ноль возвращается в кач-ве хэндла...
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re: Проблемы с pinvoke
От: Visor2004  
Дата: 05.01.12 15:39
Оценка:
Здравствуйте, Visor2004, Вы писали:

кстати говоря IL код вызова генерируется практически одинаковый и там и там.
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re[2]: Проблемы с pinvoke
От: Visor2004  
Дата: 05.01.12 15:44
Оценка:
Здравствуйте, _NN_, Вы писали:

оказалось, что корень проблемы таки в игнориовании SetLastError в аттрибуте. Реально возвращался другой код ошибки.
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re[3]: Проблемы с pinvoke
От: _NN_ www.nemerleweb.com
Дата: 05.01.12 16:21
Оценка:
Здравствуйте, Visor2004, Вы писали:

V>Здравствуйте, _NN_, Вы писали:


V>оказалось, что корень проблемы таки в игнориовании SetLastError в аттрибуте. Реально возвращался другой код ошибки.


Как я понял это баг именно с DllImportAttribute, с другими такого не происходит.

Нужно смотреть видимо в CustomAttribute.n#L226
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Проблемы с pinvoke
От: CodingUnit Россия  
Дата: 05.01.12 17:58
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Как я понял это баг именно с DllImportAttribute, с другими такого не происходит.


_NN>Нужно смотреть видимо в CustomAttribute.n#L226


в иссью трекере есть этот баг? Если нет надо завести, руки дойдут и поправим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.