DLL C++ equilavence in C# (Keyword "IN")

1

I have one problem with my importation

DLL.GetDefaultPrintInfoSp(nomImprimante, lienConfigImprimante, out DefaultPrintInfo);
idPort = DLL.OpenPortSp(nomImprimante, nomPort, false, lienConfigImprimante);
Console.WriteLine(DLL.GetLastError().ToString("X"));//0
idPrinter = DLL.CreatePrintHandleSp( ref nomImprimante,ref DefaultPrintInfo,ref lienConfigImprimante);
Console.WriteLine(DLL.GetLastError().ToString("X"));//0x30000001
Console.WriteLine(idPort + " " + idPrinter); // XXXXXXX (one IntPtr) 0

According the documentation the error 0x30000001 is "Argument is incorrect" the original definition for function is

HANDLE CreatePrintHandleSp(
IN LPTSTR lptPrinterName,
IN LPPRINTINFO lpPrtInfo,
IN LPTSTR lptCnsiniPath
);

And my importation is

[DllImport("mydll.dll")]
internal static extern IntPtr CreatePrintHandleSp(ref string lptPrinterName, ref PRINTINFO lpPrtInfo,ref string lptCnsiniPath);

I try replace REF by IN but VS don't accept it.. My struct is ok. It is use correctly by GetDefaultPrintInfoSp. I try without "ref" when I do it I have PInvokeStackImBalance

Thank you for your help

c#
c++
dll
asked on Stack Overflow Jul 23, 2014 by Boz • edited Jul 25, 2014 by Boz

2 Answers

2

There's no C# equivalent, since IN doesn't mean anything, even in C++ (it's just #define IN).

LPTSTR means long pointer (LP) to a string (STR) of TCHARS (T). For this type of parameter, you should simply pass a string in C#, the language will take care of marshalling it for you.

LPPRINTINFO means long pointer (simply pointer) to PRINTINFO, so you should marshall your structure as an unmanaged type and pass a pointer to it :

        int length = Marshal.SizeOf(typeof(PRINTINFO));
        IntPtr printInfoPtr = Marshal.AllocHGlobal(length);
        Marshal.StructureToPtr(DefaultPrintInfo, printInfoPtr, false);

, and change your function prototype:

[DllImport("mydll.dll")] internal static extern IntPtr CreatePrintHandleSp(string lptPrinterName, IntPtr lpPrtInfo, string lptCnsiniPath);

Call as: CreatePrintHandleSp(nomImprimante, printInfoPtr, lienConfigImprimante)

After you are done, you should free your unmanaged struct:

Marshal.FreeHGlobal(printInfoPtr);

Be very careful about exceptions in this part of code, since if you do not call Free you will cause memory leaks in your program. Perhaps it would be best to put the call to free in a finally block.

answered on Stack Overflow Jul 23, 2014 by axnsan • edited Jul 23, 2014 by axnsan
0

My importing Class

using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

namespace APP
{
[StructLayout(LayoutKind.Sequential)]
unsafe internal struct PRINTINFO
{
    internal uint dwCopies;// According to the documentation from SDK in C++ variable type is DWORD
    internal uint dwPrintInterval;//DWORD
    internal uint dwPrintSpeed;//DWORD
    internal uint dwPageID;//DWORD
    internal uint dwJobID;//DWORD
    internal PRINT_IMGINFO pii; // type PRINT_IMGINFO
    internal PRINT_PAPERINFO ppi; // type PRINT_PAPERINFO
    internal PRINT_CCORRECTINFO lppcc;// type LP_PRINT_CCORRECTINFO
    internal PRINT_OVLINFO lppol; // type LP_PRINT_OVLINFO
    internal PRINT_OPTION lppop; //LP_PRINT_OPTION
    internal IntPtr lpReserve1; //LPVOID
    internal IntPtr lpReserve2; //LPVOID
    internal uint dwReserve1; //DWORD
    internal uint dwReserve2; //DWORD
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRINT_IMGINFO
{
    internal uint dwSrcType; //DWORD
    internal uint dwResolutionType;//DWORD
    internal uint dwBandHeight; //DWORD
    internal uint dwSrcWidthPixels; //DWORD
    internal uint dwSrcHeightPixels; //DWORD
    internal uint dwRotate; //DWORD
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRINT_PAPERINFO
{
    internal uint dwMediaType; //DWORD
    internal uint dwUnit;//DWORD
    internal uint dwPaperWidth;//DWORD
    internal uint dwPaperHeight; //DWORD
    internal uint dwTopMargin;//DWORD
    internal uint dwBottomMargin; // DWORD
    internal uint dwLeftMargin; // DWORD
    internal uint dwRightMargin; // DWORD
    internal uint dwGapMarkLength; //DWORD
    internal uint dwLeftGap; // DWORD
    internal uint dwRightGap; // DWORD
    internal uint dwPaperID; // DWORD
    internal uint dwEdgelessFlag; // DWORD
}

[StructLayout(LayoutKind.Sequential)]
unsafe internal struct PRINT_CCORRECTINFO
{
    internal uint dwMatchingType; // DWORD
    internal uint dwBrightness; // DWORD
    internal uint dwMediaType; // DWORD
    internal uint dwHalftone; // DWORD
    internal uint dwColorExt; // DWORD
    internal PRINT_CC_REG lppccreg; // LP_PRINT_CC_REG
    internal PRINT_CC_CONDITION lppcccnd; // LP_PRINT_CC_CONDITION
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRINT_CC_REG
{
    internal UCMYK_VAL cmykPlainReg; // UCMYK_VA
    internal UCMYK_VAL cmykPluralReg; // UCMYK_VA
}

[StructLayout(LayoutKind.Sequential)]
struct UCMYK_VAL
{
    internal byte byK; // BYTE
    internal byte byC; // BYTE
    internal byte byM; // BYTE
    internal byte byY; // BYTE
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRINT_CC_CONDITION
{
    internal uint dwSingleType; // DWORD
    internal uint dwLevelCorrect; // DWORD
    internal uint dwSharpness; // DWORD
    internal int lBalanceCyan; // LONG
    internal int lBalanceMagenta; // LONG
    internal int lBalanceYellow; //LONG
    internal int lBalanceBlack; // LONG
    internal int lCCDensity; // LONG
    internal int lContrast; // LONG
}

[StructLayout(LayoutKind.Sequential)]
unsafe internal struct PRINT_OVLINFO
{
    internal uint dwOverlayType; // DWORD
    internal fixed char szFormPath[256]; //TCHAR
    internal uint dwFormID; // DWORD
    internal bool bFormIdFixed; // BOOL
}

[StructLayout(LayoutKind.Sequential)]
unsafe internal struct PRINT_OPTION
{
    internal PRINT_CUTINFO lppct; // LP_PRINT_CUTINFO
    internal uint dwFormFeed; // DWORD
    internal IntPtr lpvReserve1; // LPVOID
    internal IntPtr lpvReserve2; // LPVOID
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRINT_CUTINFO
{
    internal uint dwCutType; // DWORD
    internal uint dwCutByPageNum; // DWORD
    internal uint dwCutInPageNum; // DWORD
    internal uint dwCutConsNum; // DWORD
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRINTCMD
{
    internal byte[] lpbyCmdData; //OUT LPBYTE
    internal uint dwDataSize; //OUT DWORD
}

[StructLayout(LayoutKind.Sequential)]
internal struct STATUS_INFO
{
    internal uint dwSize; // DWORD
    internal uint dwMainStatus; // DWORD
    internal ushort wWarningStatus; // WORD
    internal ushort wErrorStatus; // WORD
    internal ushort wFatalStatus; // WORD
    internal PAGEJOB_INFO cpi; // PAGEJOB_INFO
    internal IntPtr lpcii; // LPVOID
}

[StructLayout(LayoutKind.Sequential)]
internal struct STATUS_INFO_2
{
    internal uint dwSize; // DWORD
    internal uint dwMainStatus; // DWORD
    internal ushort wWarningStatus; // WORD
    internal ushort wErrorStatus; // WORD
    internal ushort wFatalStatus; // WORD
    internal PAGEJOB_INFO cpi; // PAGEJOB_INFO
    internal IntPtr lpcii; // LPVOID
    internal uint dwSpeed; // DWORD
    internal uint dwRemainNum; // DWORD
    internal PRNPRG_INFO cppi; // PRNPRG_INFO
}

[StructLayout(LayoutKind.Sequential)]
internal struct STATUS_INFO_3
{
   internal uint dwSize; // DWORD
    internal uint dwMainStatus; // DWORD
    internal ushort wWarningStatus; // WORD
    internal ushort wErrorStatus; // WORD
    internal ushort wFatalStatus; // WORD
    internal PAGEJOB_INFO cpi; // PAGEJOB_INFO
    internal IntPtr lpcii; // LPVOID
    internal uint dwSpeed; // DWORD
    internal uint dwRemainNum; // DWORD
    internal PRNPRG_INFO cppi; // PRNPRG_INFO
    internal uint dwMyHostID; // DWORD
    internal JOBHIST cjh; // JOBHIST
}

[StructLayout(LayoutKind.Sequential)]
internal struct PAGEJOB_INFO
{
    internal uint dwSerialCount; // DWORD
    internal ushort wTotalPage; // WORD
    internal ushort wMadeCount; // WORD
    internal ushort wSetCount; // WORD
    internal ushort wJobStatus; // WORD
}

[StructLayout(LayoutKind.Sequential)]
internal struct INK_INFO_CMYK
{
    internal byte byBlackInk; // BYTE
    internal byte byCyanInk; //BYTE
    internal byte byMagentaInk; // BYTE
    internal byte byYellowInk; // BYTE
    internal byte byWasteInk; // BYTE
    internal byte byReserved; // BYTE
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRNPRG_INFO
{
    internal ushort wTotalStep; //WORD
    internal ushort wCurrentStep; // WORD
}

[StructLayout(LayoutKind.Sequential)]
internal struct JOBHIST
{
    internal uint dwJhHostID; // DWORD
    internal uint dwJobID; // DWORD 
    internal ushort wPrntCount; // WORD
    internal ushort wReserve;//WORD
}

[StructLayout(LayoutKind.Sequential)]
unsafe internal struct SETTING_INFO
{
    internal SLPTM_INFO lpcslp; // LP_SLPTM_INFO
    internal HEADADJ_INFO_1 lpchai; // LPVOID
    internal uint[] lpdwDevInfo; // LPDWORD
    internal IntPtr lpclpi; // LPVOID
}

[StructLayout(LayoutKind.Sequential)]
internal struct SLPTM_INFO
{
    internal uint dwSleepTime; // DWORD 
    internal uint dwDeepTime; // DWORD 
}

[StructLayout(LayoutKind.Sequential)]
internal struct HEADADJ_INFO_1
{
    internal CMYK_VAL cmykV; // CMYK_VAL
    internal CMYK_VAL cmykH; // CMYK_VAL
    internal uint dwHeadAdjType; // DWORD 
}

[StructLayout(LayoutKind.Sequential)]
internal struct CMYK_VAL
{
    internal byte cK; //char
    internal byte cC; //char
    internal byte cM; //char
    internal byte cY; //char
}

[StructLayout(LayoutKind.Sequential)]
internal struct DEVICE_INFO
{
    internal ushort wParticulSet; //WORD
    internal byte byOptionSet; //BYTE
    internal byte byDevAbility;//BYTE
}

[StructLayout(LayoutKind.Sequential)]
internal struct LATPOS_INFO
{
    int iCutPos; // int
    int iStopPos; // int
}

[StructLayout(LayoutKind.Sequential)]
internal struct END_INFO
{
    internal uint dwCmdType; // DWORD
    internal uint dwEndStatus; // DWORD
}

[StructLayout(LayoutKind.Sequential)]
internal struct RF_INFO
{
    internal int iSetRFIDNum; //int
    internal RFID_SET crs; // RFID_SET
}

[StructLayout(LayoutKind.Sequential)]
internal struct RFID_SET
{
    internal byte byPageId; // BYTE
    internal byte byUniqueId; // BYTE
}

[StructLayout(LayoutKind.Sequential)]
internal struct DATA_INFO
{
    internal uint dwMainteId; // DWORD
    internal int iGetDataSize; // int
}

[StructLayout(LayoutKind.Sequential)]
unsafe internal struct ORGPOS_INFO
{
    internal TK_INFO lpTKGap1; //LPTK_INFO
    internal TK_INFO lpTKGap2; //LPTK_INFO
}

[StructLayout(LayoutKind.Sequential)]
internal struct TK_INFO
{
    internal int iTPass_TKNum; // int
    internal int iReflec_TKNum; // int
}

[StructLayout(LayoutKind.Sequential)]
internal struct SLANTADJ_INFO_2
{
    internal CMYK_VAL cmykSln1; // CMYK_VAL
    internal CMYK_VAL cmykSln2; // CMYK_VAL
    internal uint dwReserved; // DWORD
}

[SuppressUnmanagedCodeSecurityAttribute] 
internal class NativeMethods
{
    [DllImport("mydll.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "GetDefaultPrintInfo")]
    internal static extern int GetDefaultPrintInfo(string lptPrinterName, out PRINTINFO lpPrtInfo);
    [DllImport("mydll.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CreatePrintHandle")]
    internal static extern IntPtr CreatePrintHandle(string lptPrinterName, IntPtr lpPrtInfo);
    [DllImport("mydll.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CreatePrintHandle")]
    internal static extern IntPtr CreatePrintHandle(string lptPrinterName, out PRINTINFO lpPrtInfo);
    [DllImport("mydll.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "StartJobCmd")]
    internal static extern int StartJobCmd(IntPtr hPrinter, PRINTCMD printcmd);
    [DllImport("mydll.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CreateJobHandle")]
    internal static extern IntPtr CreateJobHandle(string lptPrinterName, IntPtr lpPrtInfo);
    [DllImport("mydll.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "OpenPort")]
    internal static extern IntPtr OpenPort(string lptPrinterName, string lptPortName, bool bAttribute);
}
}

And my code for call the function

NativeMethods.GetDefaultPrintInfo(nomImprimante, out DefaultPrintInfo);
        idPort = NativeMethods.OpenPort(nomImprimante, nomPort, false);
        Console.WriteLine("ID Port: " + idPort + " " + Marshal.GetLastWin32Error().ToString("X"));// Result is "ID Port: 892100681 0"
        int length = Marshal.SizeOf(typeof(PRINTINFO));
        IntPtr printInfoPtr = Marshal.AllocHGlobal(length);
        Marshal.StructureToPtr(DefaultPrintInfo, printInfoPtr,true);
        idPrinter = NativeMethods.CreatePrintHandle(nomImprimante, printInfoPtr);
        Console.WriteLine("ID Printer: " + idPrinter + " " + Marshal.GetLastWin32Error().ToString("X"));// Result is "ID Port: 0 30000001"
        idPrinter = NativeMethods.CreatePrintHandle(nomImprimante, out DefaultPrintInfo);
        Console.WriteLine("ID Printer: " + idPrinter + " " + Marshal.GetLastWin32Error().ToString("X"));// Result is "ID Port: 0 30000001"

Original function format is(in C/C++)

HANDLE CreatePrintHandleSp(
IN LPTSTR lptPrinterName,
IN LPPRINTINFO lpPrtInfo
);

Do you see some error? Thanks you for help.

answered on Stack Overflow Jul 25, 2014 by Boz

User contributions licensed under CC BY-SA 3.0