Search code examples
c#c++dll.net-3.5pinvoke

.NET app call unmanged DLL, parameters contains strange characters


I am wring a .NET app to call an unmanaged DLL(Unicode).

Below is the header for the unmanaged DLL:

#pragma once

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

//  Callback function for ProcessFileAPI. The function is called whenever progress advances.
typedef VOID (CALLBACK* LPPROGRESSPROC)(CONST BYTE btProgress, LPVOID lParam);

#pragma pack(1)

//  Options for ProcessFileAPI
typedef struct _OPTIONS1
{
    BOOL m_bOption1;
    BOOL m_bOption2;
} OPTIONS1, *LPOPTIONS1;

#pragma pack()

DWORD WINAPI ProcessFileAPI(LPCTSTR lpSrcFileName, LPCTSTR lpDstFileName, LPPROGRESSPROC lpProgressProc, LPVOID lpProgProcParam,
                           LPBOOL pbCancel, CONST LPOPTIONS1 lpOptions1);

#ifdef __cplusplus
}
#endif

And the .cpp for unmanaged DLL:

extern "C"  DWORD WINAPI ProcessFileAPI(LPCTSTR lpSrcFileName, LPCTSTR lpDstFileName, LPPROGRESSPROC lpProgressProc, LPVOID lpProgProcParam,
                                       LPBOOL pbCancel, CONST LPOPTIONS1 lpOptions1)
{
    TRACE(_T("SrcFileName: %s. DstFileName: %s."), lpSrcFileName, lpDstFileName);
    return  0;
}

Below is the .NET code for the function:

using System;
using System.Runtime.InteropServices;

namespace SDKAPI
{
    public struct TOptions1
    {
        public bool bOption1;
        public bool bOption2;
    }   // end TOptions1

    public delegate void TProgressProc(byte btProgress, IntPtr lParam);
}

namespace SDKAPI.Units
{
    public class SDKAPI
    {
        [DllImport("SDK.DLL")]
        public static extern uint ProcessFileAPI(string lpSrcFileName, string lpDstFileName, TProgressProc pgrsproc, IntPtr lpProgProcParam, ref int pbCancel, ref TOptions1 options);

    } // end SDKAPI
}

And below is the calling of the function:

Options1.bOption1 = true;
Options1.bOption2 = false;

// Process the file
FCancel = 0;

RetCode = SDKAPI.Units.SDKAPI.ProcessFileAPI(txtSrcFile.Text, txtDstFile.Text, new SDKAPI.TProgressProc(this.ProgressProc), IntPtr.Zero, ref FCancel, ref Options1);

When calling the DLL with txtSrcFile.Text = "a" and txtDstFile.Text = "b", but I debug in the DLL and find the parameter lpSrcFileName becomes "a" then followed with many strange characters. Why?


Solution

  • You need to find out whether the unmanaged DLL is using Unicode or not. If yes you need CharSet.Unicode otherwise CharSet.Ansi.

    You also need to set the pack.

    [StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct TOptions1
    {
        public bool bOption1;
        public bool bOption2;
    }
    
    [UnmanagedFunctionPointer(CallingConvention.Winapi)]
    public delegate void TProgressProc(byte btProgress, IntPtr lParam);
    
    [DllImport("SDK.DLL", CharSet = CharSet.Unicode)]
    public static extern uint ProcessFileAPI(
        string lpSrcFileName, string lpDstFileName, TProgressProc pgrsproc,
        IntPtr lpProgProcParam, ref bool pbCancel, [In] in TOptions1 options);