none
64 bit app calling 32 bit dll? RRS feed

  • Question

  • I am working on an application solution that builds a .exe and a few .dlls.  The .exe and one of the .dlls get built for "Any CPU" and run fine on both 32-bit XP and 64-bit Windows 7.  The second .dll gets built as "Win32" and runs fine on the 32-bit XP system.

    However, when I try and run the app on 64-bit Windows 7, the .exe starts, makes calls to the first .dll ("Any CPU" one) and then that .dll calls the "Win32" .dll.  Execution seems to stop at this point - the program (A GUI) just sits there endlessly and has to be terminated.

    How will I get around this?  Also, the second .dll, when working on 32-bit XP, makes some calls to some pre-built DLLs that were compiled as 32 bit.  Will I not be able to get around this last part?

    At first, I'd be happy if someone could tell me how to get the "Win32" compiled dll to execute.  I haven't had any luck changing the build to "x64".

    Sunday, January 29, 2012 10:46 PM

Answers

  • A 64bit executable cannot call a 32bit dll and viceversa. Unless you actually need your application to be 64bit, the simplest option is to set it to target x86. This will still allow it to run on both 32 and 64bit versions of Windows.

    If for some reason this is inapplicable, a possible solution would be to create a separate 32bit process that would load the 32bit dll, and have your 64bit application communicate with the other process, possibly using IPC (in some trivial case, redirecting the standard input and output can also work, or even just inspecting the return value of the process). In any case, this results in some extra work; I would advise you to review accurately your requirements first.

    HTH
    --mc

    • Proposed as answer by CoolDadTxModerator Tuesday, January 31, 2012 3:47 PM
    • Unproposed as answer by msnhelpsme Wednesday, February 1, 2012 3:20 PM
    • Marked as answer by msnhelpsme Friday, February 3, 2012 8:11 PM
    Sunday, January 29, 2012 11:17 PM
  • To answer your questions:

    (With another question) Is the 'Win32' application C# or C++? Win32 *should* be the same as x86, but I would try to add an x86 configuration and copy settings from the x64 if possible. If its a C++ library, the whole compilation process is different. Where did the Win32 dll come from?

    The easiest way to ensure project references is to delete the references from the Project Explorer, and then re-add them as project and not browse references.

    • Marked as answer by msnhelpsme Friday, February 3, 2012 8:13 PM
    Tuesday, January 31, 2012 7:12 PM

All replies

  • A 64bit executable cannot call a 32bit dll and viceversa. Unless you actually need your application to be 64bit, the simplest option is to set it to target x86. This will still allow it to run on both 32 and 64bit versions of Windows.

    If for some reason this is inapplicable, a possible solution would be to create a separate 32bit process that would load the 32bit dll, and have your 64bit application communicate with the other process, possibly using IPC (in some trivial case, redirecting the standard input and output can also work, or even just inspecting the return value of the process). In any case, this results in some extra work; I would advise you to review accurately your requirements first.

    HTH
    --mc

    • Proposed as answer by CoolDadTxModerator Tuesday, January 31, 2012 3:47 PM
    • Unproposed as answer by msnhelpsme Wednesday, February 1, 2012 3:20 PM
    • Marked as answer by msnhelpsme Friday, February 3, 2012 8:11 PM
    Sunday, January 29, 2012 11:17 PM
  • I am fairly certain that because of the underlying dll that is only 32bit, you are stuck with building your application to 32bits (x86) only.
     
    It may be possible to isolate the 32 bit portions of your code as a separate service and call this from a separate 64 bit process through some interprocess means.  Do you actually need 64 bit capabilities because of large memory needs?

    --
    Mike
    Sunday, January 29, 2012 11:18 PM

  • Sorry, I did not copy your idea, but rather was posting the same thoughts while you were.

    --
    Mike
    Sunday, January 29, 2012 11:27 PM
  • Ok, regarding making them all 32 bit.  When I look at the build config for the 64 bit exe and dll, the other option besides "Any CPU" is "x86" not "Win32".  I would assume these would be the same, but when I do a "Rebuild All" I still see the same issue - the program hangs once the function inside the "Win32" dll gets called.

    Is there anything else to do besides just switching the build config from "Any CPU" to "x86"?

    Monday, January 30, 2012 12:37 AM
  • Any more comments on this please?
    Monday, January 30, 2012 1:16 PM
  • A possible explanation is that your 32bit dll might have a dependency on a 16bit dll: while these can run on Windows 32bit, using WoW32, they are unsupported in Windows 64bit.

    If you don't control all the components you reference, you may want to use Dependency Walker or similar tools to get a full list of your dependencies.

    This explanation only works if the DLL is lazy loaded and you are catching the exception that is normally generated. If none of the above applies, it may well be that your code makes a few wrong assumptions when running on a 64bit system. It might help if you could debug what happens when the 32bit dll is called and/or provide a few more details about the offending DLL and the way it's called.

    HTH
    --mc


    • Edited by Mario Cossi Monday, January 30, 2012 3:23 PM
    Monday, January 30, 2012 3:17 PM
  • If none of the above applies, it may well be that your code makes a few wrong assumptions when running on a 64bit system (typically, you may be storing a pointer into an Int32 instead of using an IntPtr). It might help if you could debug what happens when the 32bit dll is called and/or provide a few more details about the offending DLL and the way it's called.

    HTH
    --mc


    The DLL giving me troubles is 32-bit.  What is happening is this:

    The .exe, which initially was built as "Any CPU", calls a constructor:   [code]X x = new X();[/code] for example.  That constructor code is part of the 32-bit DLL, built as "Win32" in configuration mgr.

    I understand the part about the 64-bit not being able to call the 32-bit.  So the solution would seem to be to build the .exe as 32-bit, right?  So in configuration mgr I changed "Platform" from "Any CPU" to "x86" and did a rebuild all.  But I still have the same problem.  Is "x86" not the same as "Win32"?  If it is the same, then why does the program hang when the constructor is called when running on 64-bit Windows?

    Monday, January 30, 2012 3:26 PM
  • Here is another clue that might be of help: when I take the code back to the 32-bit XP system (where it has always worked) and I change the config so the "Any CPU" builds become "x86" then it doesn't even work on 32-bit Windows.  It hangs in the exact same place as what I have described above - the call to the constructor in the "Win32" .dll.

    Is there some setting behind the scenes or something?

    What works:

              -building the .exe and one .dll as "Any CPU" and building the other .dll as "Win32" and running this on 32-bit Windows XP.

    What doesn't work:

              -building the .exe and one .dll as "x86" and building the other .dll as "Win32" and running on 32-bit Windows XP.

              -taking "What works" above and running on 64-bit Windows 7 (obviously, since 64 bit can't call 32-bit DLL)

     

    Does this clue help anyone see what is going on?  I am really stumped now.  Perhaps it has something to do with that one DLL being built as "Win32"???  Why isn't that option available for the other projects?

    Monday, January 30, 2012 4:34 PM
  • Are you sure you're grabbing the correct exe and dlls from the output folders?

    When you build in specifically x86 or x64 mode, the bin directory gets an additional folder in it where it sticks the output files.

     

    What the others are suggesting however, is that ALL of the projects in your solution should be set to build as x86, and they should all reference each other as project references (opposed to direct dll references, which dont get updated when you change build configurations).

    When you want to build something as x86, you have to create that configuration in the configuration manager manually by right-clicking the Solution and going to Configuration Manager. Add the x86 option and choose 'copy settings from: Any CPU'.

    Monday, January 30, 2012 9:48 PM
  • Are you sure you're grabbing the correct exe and dlls from the output folders?
    When you build in specifically x86 or x64 mode, the bin directory gets an additional folder in it where it sticks the output files.
     
    Yes, I checked that and made sure I was testing the one I thought I had built. The x86 one does get put into a deeper subdirectory. Interestingly enough, even though the "Any CPU" .exe and "x86" .exe are not identical, they are exactly the same size in bytes. Is this normal, or should this be indicating to me that they are pretty much the same build? There are like 5 lines of differences, but if I simply rebuild the same .exe at a later time, it will have 4 lines of differences from the previous build, even if nothing changed.
    What the others are suggesting however, is that ALL of the projects in your solution should be set to build as x86
    The "Win32" .dll doesn't have an "x86" option in Configuration Manager - the only other option is "x64". Are "Win32" and "x86" EXACTLY the same?
    and they should all reference each other as project references (opposed to direct dll references, which dont get updated when you change build configurations).
    How can I check and see if this is the case or not?
    When you want to build something as x86, you have to create that configuration in the configuration manager manually by right-clicking the Solution and going to Configuration Manager. Add the x86 option and choose 'copy settings from: Any CPU'.
    I had done this, yes.
    Monday, January 30, 2012 10:46 PM
  • Interestingly enough, even though the "Any CPU" .exe and "x86" .exe are not identical, they are exactly the same size in bytes. Is this normal, or should this be indicating to me that they are pretty much the same build? There are like 5 lines of differences, but if I simply rebuild the same .exe at a later time, it will have 4 lines of differences from the previous build, even if nothing changed.

    There are timestamps in the compiled assembly. I guess that's the 4 lines of differences.

    The fifth is a flag: COMIMAGE_FLAGS_32BITREQUIRED. It indicates that it can only be loaded into a 32-bit process.

    Tuesday, January 31, 2012 8:57 AM
  • Interestingly enough, even though the "Any CPU" .exe and "x86" .exe are not identical, they are exactly the same size in bytes. Is this normal, or should this be indicating to me that they are pretty much the same build? There are like 5 lines of differences, but if I simply rebuild the same .exe at a later time, it will have 4 lines of differences from the previous build, even if nothing changed.

    There are timestamps in the compiled assembly. I guess that's the 4 lines of differences.

    The fifth is a flag: COMIMAGE_FLAGS_32BITREQUIRED. It indicates that it can only be loaded into a 32-bit process.


    Actually, this is the 64-bit .exe I am referring to, not the 32-bit DLL I try and load.  But does it make sense that the 64-bit and 32-bit DLLs are the same size?
    Tuesday, January 31, 2012 3:43 PM
  • I don't see any reason for them to not be the same size. The IL is the same. The real difference should be in the code generated by the JIT compiler, at runtime.
    Tuesday, January 31, 2012 4:08 PM
  • I don't see any reason for them to not be the same size. The IL is the same. The real difference should be in the code generated by the JIT compiler, at runtime.


    Ok, that sounds correct then.  I just wanted to make sure.  So I was thinking it might have something to do with "project references versus direct dll references" as another poster had mentioned.  So I went into the Properties page of the .exe (which had been 64 bit, now I am building as x86) and I set Reference Paths to refer to the containing folder of the 32-bit DLL.  In other words, the Reference Paths now has

    [code]C:\SomePath\32bitDLLProjectName\[/code]

    where C:\SomePath\32bitDLLProjectName\ contains the Debug and Release directories for the 32-bit DLL.  Is this the correct thing to do?

    Also, note that when I set the .exe to build as x86 then it hangs on the 32-bit Windows XP system (the Any CPU version would at least work with the 32-bit DLL on Windows XP).  So another thing to consider is why does changing the .exe build from "Any CPU" to "x86" cause it to not work on 32-bit Windows XP?

    Tuesday, January 31, 2012 4:34 PM
  • To answer your questions:

    (With another question) Is the 'Win32' application C# or C++? Win32 *should* be the same as x86, but I would try to add an x86 configuration and copy settings from the x64 if possible. If its a C++ library, the whole compilation process is different. Where did the Win32 dll come from?

    The easiest way to ensure project references is to delete the references from the Project Explorer, and then re-add them as project and not browse references.

    • Marked as answer by msnhelpsme Friday, February 3, 2012 8:13 PM
    Tuesday, January 31, 2012 7:12 PM
  • Is the 'Win32' application C# or C++? Win32 *should* be the same as x86, but I would try to add an x86 configuration and copy settings from the x64 if possible. If its a C++ library, the whole compilation process is different. Where did the Win32 dll come from?

    The easiest way to ensure project references is to delete the references from the Project Explorer, and then re-add them as project and not browse references.

    The "Win32" DLL is C++.  I can't seem to add an x86.  When I right-click on it and select Properties the values for "Platform" are

    • Active(Win32)
    • Win32
    • x64
    • All Platforms

    and when I click "Configuration Manager..." under the 'Platform' category I only see "Win32", "x64", and "<Edit...>" and when I select "<Edit...>" the only choice I have is to remove "Win32" or "x64".  I removed "x64" and then under 'Platform' I now see "<New...>" but when I select it the only option for "New platform:" is "x64".

    As for where the C++ "Win32" DLL came from, it was written to communicate with other pre-compiled 32-bit DLLs (getting those to work is not a concern right now).  So I have control over the source of this C++ "Win32" DLL.


    Regarding project references, in the Solution Explorer in VS2008, under the .exe project, there is a References "tree".  When I expand it, I see the name of the 32-bit Win32 DLL.

    1. I deleted this.
    2. I right-clicked on References, Add Reference..., Projects, and selected the name of the Win32 DLL.

    is this what you meant?  I am still suffering from the same problems as before.  1) it doesn't work on 64-bit Windows 7 and 2) when the .exe is built for "x86" then it doesn't work on 32-bit windows either.  It freezes at the exact same place, when it first calls into the 32-bit Win32 DLL.

    Tuesday, January 31, 2012 9:09 PM
  • You're adding the project reference correctly.

    I wonder if you're getting an unhandled exception in the C++ code which is bringing your app down. Its either that, or some blocking call is freezing your UI thread.

    http://www.microsoft.com/download/en/details.aspx?id=26798 There is a tool called DebugDiag which can help you take a crash dump or a minidump of a running (or crashing) application. The link there takes you to the download. Its pretty easy to use, just pick the right version for the processor architecture you're using. This will show you any exceptions the program has had during its run and might provide some more clues.

    Based on what you've told us, I don't think the problem is really the x86 (Win32) or the x64. Sounds like it might be a bug or error in the native library. Can you add some logging to whatever method you're calling out to? Just dump some text to a file every so often and see where its hanging?

     

    Thursday, February 2, 2012 6:14 PM
  • When you want to build something as x86, you have to create that configuration in the configuration manager manually by right-clicking the Solution and going to Configuration Manager. Add the x86 option and choose 'copy settings from: Any CPU'.

    I actually noticed a difference when I copied settings from "<Empty>" instead of "Any CPU" - I think anyways.  Something to keep in mind in case someone else gets stuck with this.
    Friday, February 3, 2012 8:15 PM