P / Invoke and 64-bit development

    Recently, in my WPF application, there was again a need for ClearType postprocessing, i.e. Adding ClearType-like properties to graphics that are initially rendered in the "normal" way. Again, unmanaged code was selected (Intel C ++ stack, OpenMP), but this time I wanted to interact in a 64-bit environment. Here's a story about how “fun” it was.

    These are some wrong bees
    I do it means a 64-bit C ++ Win32 DLL application ... and the first thing I see after the wizard has generated files is this charm:

    To be honest, the x64 option appears as configurations somewhere in 50% of cases, and this happens for no particular reason. Nevertheless, I had to delve into the Internet in order to understand that you need to create a configuration in Configuration Manager. No sooner said than done. The x64 configuration can, in principle, be selected from the list.

    Deciding to save time on the configuration, I decided to copy the Win32 settings. Everything worked fine, with the exception that all .Net projects in the configuration began to target Win64 . But the project would have compiled, but I would not have known anything - if PostSharp had not been tied up with me. I don’t know what the cant was, but PostSharp “delivered” in a 64-bit conf with error messages that did not fit on the screen.

    I had to change the configuration manually.

    Stop, where's my dll?
    In general, to build a DLL, it is not enough just to click Build Project when an open file from the project. Unlike C # projects (as well as from Microsoft C ++ projects), the Build Project option on the open file is simply not there! You have to right-click on the solution and select Build. I don’t know who at Intel is responsible for usability, but IMHO this is a serious jamb.

    One puzzle that awaits newcomers to C ++ development in VS is that the DLL is generated, but cannot be found later. Trying to find the DLL in the Debug or Release folder of the corresponding project will give this:

    The problem is that Visual C ++ puts the DLL itself at the solution level, and not at the specific project. So look for a few folders above. Perhaps this is some kind of logic, but as a donor I do not see her point blank.

    We pay import duties
    At this stage, refused to work [DllImport]. More precisely, he did not start working. .Net simply could not find the labels, despite the fact that I correctly registered the Calling Convention. After spending half an hour in Google, I came to the conclusion that DllImport is not able to work with 64-bit libraries . It will work more precisely, but only after you doDUMBIN /EXPORTS and start defining P / Invoke methods like this:


      CallingConvention = CallingConvention.Cdecl, 

      ExactSpelling = true, 

      EntryPoint = "?Coalesce@@YAXPEAE0HHH@Z")] // <-- whoops!
    public static extern void Coalesce(IntPtr src, IntPtr dst, 

      int width, int height, int stride);

    I will not comment on the “elegance” of such a decision here because everyone is surely so clear. Unfortunately, nothing still works at this point.

    There is a desire to “score”
    In a super-mega-ideal world, a .Net project at the time of collection could have made it clear that if I registered a dependency on another C ++ project, I would have to copy the result of the work of the dependent project to the Debug / Release folder. And in the real world, the main project is to make the Post-Build Step which will copy the DLL to the desired folder. Moreover, it is desirable to do this precisely for a C ++ project, because building and starting a .Net consumer does not always start the Post-Build Step . The reasons for this, I think, are obvious.

    Nevertheless, after all these manipulations, the project started working. Gaining insolence, I added support for OpenMP, after which the application successfully crashed with the error "An attempt was made to load an image in incorrect format" which, translated into human language, means that the lib is tied to some other lib that is not to find . Agree, the information content of the error text is simply amazing - especially after you spend an hour picking the project settings based on the assumption that you really started generating the DLL in some kind of "incorrect" format.

    In this situation, he saved me again DUMPBIN. It turned out that, unlike using OpenMP under the Microsoft compiler, Intel'evsky is tied to a certain librarylibiomp5md.dllwhich naturally bindoes not fall into the folder (and of PATHcourse, also into the variable ). We are raiding. It seems to work.

    Last nail
    The code for my x64 library was taken directly from the 32-bit project, so initially it did not want to work (due to changes in pointer arithmetic). So I stupidly set a breakpoint in my DLL, turned on Unmanaged Code Debugging and hit F5. Result?

    I will not describe here the tweaks and jumps that I did to make debugging work. In short, the bottom line was to register my managed program as a starting process for a DLL. After numerous attempts, I decided to quit this venture. Surely there is a possibility of such a debugging but I personally think that you need to sit and wait stupidly 2010 th studio where possiblethis problem is resolved.

    Close the case
    Despite all my dissatisfaction with what is happening, I completed the library. Of course, I don’t have to talk about high-quality debugging, but I was lucky - the algorithms themselves are quite simple and, moreover, they have already been tested in a 32-bit environment, so all that was left to do was to clear up the understanding of what sizeof(void*) != sizeof(DWORD). Everything worked, and it works now, in the background, while I am writing this post (algorithms are used for headings). By and large, these algorithms work 15-20 times faster than their .Net analogs.

    I basically understand that perhaps you should not go into 64-bit development now, when for most tasks this is absolutely optional. I just really wanted to try, touch the rake. And despite the fact that some of the problems that I described are probably the result of my own stupidity and ignorance, the mezanism of developing 64-bit applications seems to me a bit complicated and confusing. Besides, at the moment it seems more appropriate for me to draw text using Direct2D and DirectWrite technologies, which I am actively studying and about which I may write on Habré.

    That's all, thanks for watching! See you soon!

    Also popular now: