Search code examples
c#delphipinvoke

How should I import Powerflex functions for use in C#?


I have been given the task of using pfxlibn.dll in Visual Studio 2010 C#, which from what I can make out is a Powerflex library. http://pfxcorp.com/clib-fns.htm

I have tried a few variations of importing the PclGetField function, for example:

[DllImport("pfxlibn.dll", SetLastError = true)]
public static extern void PclGetField(
    Int32 iHandle, 
    Int32 iFieldNum, 
    [MarshalAs(UnmanagedType.LPStr)] string Date
    ); 

[DllImport("pfxlibn.dll",
    CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi,
    EntryPoint = "PclGetField")]
public static extern int PclGetField(Int32 iHandle, Int32 iFieldNum, string Data)

[DllImport("pfxlibn.dll", EntryPoint = "PclGetField",
    ExactSpelling = true,
    CharSet = CharSet.Ansi,
    CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 PclGetField(Int32 iHandle, Int32 iFieldNum,[MarshalAs(UnmanagedType.VBByRefStr)] ref string input);

So far, none of the above have worked. Or variations of the above.

Within Delphi the code looks like

pTmpBuf           : PChar;

iLastErr := PclGetField(fHandle,iField,pTmpBuf);

Solution

  • The documentation you link to is very sparse so to answer the question we need to guess somewhat.

    The functions you need are these:

    aResult PCLENTRY PclGetField (aDHandle fdh, anInt eno, aString data);
    //Retrieves the formatted value of a field from a file buffer.
    
    aResult PCLENTRY PclGetFieldLen (aDHandle fdh, anInt eno, anInt *length); 
    //Gets the length of a field.
    

    In order to know for sure how to handle this we need more information:

    • What does the PCLENTRY macro evaluate to? I'm going to assume __stdcall, but you will need to check your header file.
    • What is aResult? I'm going to assume int but you will need to check your header file.
    • What is aDHandle? I'm going to assume void* or INT_PTR but you will need to check your header file.
    • What is anInt? I'm going to assume int but you will need to check your header file.
    • What character set is used? ANSI or Unicode? I'm going to assume ANSI.

    You are going to need to call PclGetFieldLen to find out how big a buffer you need. And then you will allocate that buffer and call PclGetField to populate it. You will need to find out whether or not the value returned by PclGetFieldLen includes the zero-terminator or not. I'm assuming that it does not.

    With these assumptions you would write the pinvoke like this:

    [DllImport("pfxlibn.dll", CallingConvention=CallingConvention.Stdcall)]
    public static extern int PclGetFieldLen(fdh IntPtr, int eno, out int length); 
    
    [DllImport("pfxlibn.dll", CallingConvention=CallingConvention.Stdcall,
        CharSet=CharSet.Ansi)]
    public static extern int PclGetField(fdh IntPtr, int eno, StringBuilder data);
    

    You can then call the functions like this:

    IntPtr fdh = .... // whatever function creates the database handle
    int eno = .... // get the field number from somewhere
    int length;
    int res = PclGetFieldLen(fdh, eno, out length);
    //check res for errors
    StringBuilder data = new StringBuilder(length);
    res = PclGetFieldLen(fdh, eno, data);
    string field = data.ToString();
    

    Since we don't know all the details, there are a bunch of unknowns in this answer. You have the header file, and you can contact the library vendor to resolve the unknowns. But hopefully the outline above tells you what questions need to be answered.