views:

151

answers:

3

Hello,

I got a C++ dll which has to be integrated in a C# project.

I think I found the correct way to do it, but calling the dll gives me this error: System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)

This is the function in the dll:

extern long FAR PASCAL convert (LPSTR filename);

And this is the code I'm using in C#

namespace Test{
public partial class Form1 : Form
{
    [DllImport("convert.dll", SetLastError = true)]
    static extern Int32 convert([MarshalAs(UnmanagedType.LPStr)] string filename);

    private void button1_Click(object sender, EventArgs e)
    {
        // generate textfile
        string filename = "testfile.txt";

        StreamWriter sw = new StreamWriter(filename);
        sw.WriteLine("line1");
        sw.WriteLine("line2");
        sw.Close();

        // add checksum
        Int32 ret = 0;
        try
        {
            ret = convert(filename);

            Console.WriteLine("Result of DLL:  {0}", ret.ToString());
        }
        catch (Exception ex)
        {
            lbl.Text = ex.ToString();
        }
    }
}}

Any ideas on how to proceed with this?

Thanks a lot, Frank

+2  A: 

Try to switch your C# code from AnyCPU to x86 (in Properties dialog).

Josip Medved
same result ...System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
Frank
@Frank: Exception points to x86/x64 mismatch in DLL and C# code. If C++ code is compiled as x64, try setting C# code also to x64 (and vice-versa if code is x86). When dealing with DllImport, that is only cause for that exception (as per Microsoft documentation - http://msdn.microsoft.com/en-us/library/system.badimageformatexception.aspx).
Josip Medved
+3  A: 

Your exported function uses the PASCAL calling convention, which in Windows is the same as stdcall. The .Net runtime needs to know about that, so modify your C# method signature as follows:

[DllImport("convert.dll", SetLastError = true, CallingConvention=CallingConvention.StdCall)]
static extern Int32 convert([MarshalAs(UnmanagedType.LPStr)] string filename);
Frank Bollack
there was an ) too much at the first line, so removed this:[DllImport("convert.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]static extern Int32 convert([MarshalAs(UnmanagedType.LPStr)] string filename);but still the same errorSystem.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
Frank
Can you please give some more details about your platform, project settings and the DLL used. (Architecture x86/x64 etc)
Frank Bollack
+2  A: 

try to use __stdcall (or WINAPI or APIENTRY) in the function exported from the DLL.

Oleg
He already has. From WinDef.h `#define PASCAL __stdcall`
Joe Gauterin
I have to use the dll "as is" ... no changes allowed
Frank
There are different declaration of PASCAL in different headers (also in WinDef.h), but dierct usage of `__stdcall` will be allways interpreted in the same way
Oleg
@Frank: Ohhh! The DLL is not from your code, than probably the DLL has really another format like 64-bit etc?
Oleg
@Oleg: unfortunately no documentation at all about the dll ...
Frank
You can use dumpbin.exe with /headers parameter from Visual Studio or dependency walker www.dependencywalker.com to see more information about dll
Oleg
pffff... dependency walker shows:Error: at least one file was not a 32-bit or 64-bit Windows moduleNo PE signature found. This file appears to be a 16-bit Windows module.I could be wrong, but this doesn't seem to look good...
Frank
a 16-bit Windows module or a DOS Program can be all dumped with `dumpbin.exe /headers convert.dll`. You can also open the DLL with a text editor and verify is the first 2 bytes are 'MZ'.
Oleg
indeed starts with MZ.!so what you mean is that it can be converted with dumpbin.exe ?
Frank
Not converted but examined. What kind of DLL you have. For which processor it is compiled. If it DOS/Windows/OS2 etc dll etc. After you will know more about the DLL you can decide what to do. One more question: what is that DLL? Is it a part of well known product? Can it be free downloaded?
Oleg
no it's not free, but part of a larger project (embedded software) I have to generate datafiles for. tried dumpbin, result: warning LNK4094: is an MS-DOS executable; use EXEHDR to dump it
Frank
The reason can be different. I have problem to give a recommendation without more information. It can be, for example, that you downloaded the DLL from FTP with ASCII instead on IMAGE type and you have CR LF instead of all CR in you binary. It can be that you receive the corrupted DLL with other way. If can be a lot of reason, why you have so strange DLL. At least it is clear, that you have not a problem with C# import declaration, but you have NOT correct Windows DLL at all.
Oleg
Thanks a lot Oleg. I will contact the supplier of it to deliver me a new version compiled for usage on x86
Frank