📜 ⬆️ ⬇️

P / Invoke and 64-bit development

Recently, in my WPF application, the need for ClearType postprocessing arose again, i.e. adding a ClearType-like graphics property that is initially rendered in the “normal” way. The unmanaged code was selected again (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 kind of irregular bees.
What I do is a 64-bit C ++ Win32 DLL application ... and the first thing I see after the wizard has downloaded the files is this beauty:


')

To be honest, the x64 option appears as configurations about 50% of the time, and this happens for no particular reason. However, I had to dig in 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.




Having decided 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 be compiled, but I would not know anything - if I had not tied up PostSharp. I don’t know what the jamb is, but PostSharp “rendered” in a 64-bit config with such error messages that they didn’t fit into the screen.

I had to change the configuration manually.

Stop, and where is my dll?
In general, to build a DLL, it is not enough just to open the file from the project and click the Build Project. Unlike C # projects (as well as Microsoft C ++ projects), the Build Project option on an open file simply does not exist! You have to right-click on the solution and choose Build. I do not know who in Intel is responsible for usability, but IMHO is a serious joint.




One puzzle that expects newbies in C ++ development in VS is that the DLL is generated, but then it cannot be found. Attempting to find a DLL in the Debug or Release daddy of the corresponding project will result in this:




The problem is that Visual C ++ puts the DLL itself at the solution level, and not at the specific project. So look for several folders above. Perhaps there is some kind of logic in this, but I don’t see it as a point-blank.

We pay import duties
At this stage, refused to work [DllImport] . More precisely, he did not begin to work. .Net simply did not find tags, despite the fact that I correctly registered the Calling Convention. Having spent half an hour in Google, I came to the conclusion that DllImport does not know how to work with 64-bit libraries . It will work more precisely, but only after you make DUMBIN /EXPORTS and begin to define the P / Invoke methods like this:

[DllImport( "Typografix.Bitmap.dll" , <br/>
CallingConvention = CallingConvention.Cdecl, <br/>
ExactSpelling = true , <br/>
EntryPoint = "?Coalesce@@YAXPEAE0HHH@Z" )] // <-- whoops!
public static extern void Coalesce(IntPtr src, IntPtr dst, <br/>
int width, int height, int stride);<br/>

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

There is a desire to "score"
In a super-mega-ideal world, .Net project at the time of gathering could cut through that if I registered his dependency on another C ++ project, then it would be necessary to copy the result of the dependent project's work into the Debug / Release folder. And in the real world, the main project has to do the Post-Build Step, which will copy the DLL to the correct folder. And it is desirable to do this for the C ++ project, since building and launching a .Net consumer does not always launch the Post-Build Step . The reasons for this, I think, are obvious.

However, after all these manipulations, the project has earned. Having gained impudence, I added support for OpenMP, after which the application safely fell with the error “in incorrect format”, which, translated into human language, means that the lib is bound to some other language that is not to find . Agree, the informational content of the error text is simply amazing - especially after you spend an hour picking up the project settings based on the assumption that you really started generating the DLL in some kind of "incorrect" format.

In this situation, DUMPBIN saved me again. It turned out that, unlike using OpenMP under the Microsoft compiler, Intel'evsky is tied up with a kind of libiomp5md.dll library which naturally doesn’t fall into the bin folder (and the PATH variable, of course, too). We ruin. 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). Therefore, I stupidly set a breakpoint in my DLL, turned on Unmanaged Code Debugging and pressed F5. Result?




I will not describe here the grimaces and jumps that I did to make debugging work. In short, the point was to register my managed program as a starting process for DLLs. After numerous attempts, I decided to quit this venture. Surely there is a possibility of such debugging, but personally it seems to me that it is necessary to sit and stupidly wait for 2010 studio where this problem is probably ruined.

Close the case
Despite all my dissatisfaction with what is happening, I completed the library. Of course, there is no need to talk about high-quality debugging, but I was lucky - the algorithms themselves are quite simple and, moreover, they were already tested in a 32-bit environment, so it only remained to clean up in my head the understanding that sizeof(void*) != sizeof(DWORD) . Everything worked, and it works now, in the background, while I am writing this post (the algorithms are used for headings). On a vskidku, these algorithms work 15-20 times faster than their .Net analogs.

I basically understand that maybe you shouldn’t go into 64-bit development now, when for most tasks it is absolutely optional. I just really wanted to try, ponastupat on a rake. And despite the fact that some of the problems that I described are probably a consequence of my own stupidity and ignorance, the mezanism of developing 64-bit applications seems to me too complicated and confusing. In addition, at the moment it seems to me more appropriate to use Direct2D and DirectWrite technologies for text drawing, which I actively study and about which I will probably write on Habré.

That's all, thank you for your attention! See you again!

Source: https://habr.com/ru/post/68837/


All Articles