none
Unmanaged DLL RRS feed

  • Question

  • Exellent night!

    In a pascal example code, I make the following excerpt:

    unit dllTeste;
    
    interface
    
    uses Windows;
    
    Type
      AbastPAF2 = record
        value: boolean;
        total_dinheiro: currency;
        total_litros: double;
        PU: currency;
        tempo: integer;
        codbico: string[2];
        numbico: integer;
        numtanque: integer;
        voltanque: integer;
        codcombustivel: integer;
        seriecbc: integer;
        tipocbc: char;
        datetime: TDatetime;
        st_full: string[123];
        registro: integer;
        encerranteI: double;
        encerranteF: double;
        integridade: boolean;
        checksum: boolean;
        tag1: string[16];
        tag2: string[16];
      end;
    
    {$IFNDEF EMPLOYER}
    
    Function InicializaSocket2(ip: ansistring;porta:integer): boolean; stdcall;
    Function LeAbastecimentoPAF2(NumReg:integer): AbastPAF2; stdcall;
    
    {$ENDIF}
    
    implementation
    
    {$IFNDEF EMPLOYER}
    
    Function InicializaSocket; external 'EMPLOYER.DLL' name 'InicializaSocket';
    Function LeAbastecimentoPAF2; external 'EMPLOYER.DLL' name 'LeAbastecimentoPAF2';
    
    {$ENDIF}
    
    end.


    Then I can use the DLL in code. However in C # I can only replicate the "InitializeSocket". My goal is just to make it work, then I improve the code:

    using System;
    using System.Runtime.InteropServices;
    
    namespace WindowsFormsApp
    {
        public static class TesteExtracao
        {
            [DllImport("EMPLOYER.dll", EntryPoint = "InicializaSocket")]
            public static extern Boolean OpenSocket(string ip);
    
            [DllImport("EMPLOYER.dll", EntryPoint = "LeAbastecimentoPAF2")]
            public static extern AbastPAF2 ReadSupply(int numReg);
        }
    
        [StructLayout(LayoutKind.Sequential)]
        public struct AbastPAF2
        {
            public bool value;
            public decimal total_dinheiro;
            public double total_litros;
            public decimal PU;
            public int tempo;
            public string codbico;
            public int numbico;
            public int numtanque;
            public int voltanque;
            public int codcombustivel;
            public int seriecbc;
            public char tipocbc;
            public DateTime datetime;
            public string st_full;
            public int registro;
            public double encerranteI;
            public double encerranteF;
            public bool integridade;
            public bool checksum;
            public string tag1;
            public string tag2;
        }
    
    }

    And on the call:

    if (NativeMethods.InicializaSocket2(IP, 2001))
                {
                    btnClose.Enabled = true;
                    btnConnect.Enabled = false;
    
                    Models.Type.AbastPAF2 ab = NativeMethods.ReadSupply(1480);
                    var Checked = ab.checksum;
                    var integridade = ab.integridade;
                    var value = ab.value;
                    var EditTotaisDin = ab.total_dinheiro;
                    var EditCanal = ab.codbico;
                    var EditPPL = ab.PU;
    
                    var EditData = ab.datetime;
                    //var EditHora = ab.datetime;
                    var EditTempo = ab.tempo;
                    var EditEnc = ab.encerranteI / ab.encerranteF;
                    var EditRegistro = ab.registro;
                    var EditTotaisLT = ab.total_litros;
                    var EditString = ab.st_full;
    
                    rchTxtBxLog.AppendText($@"--------------------------------
                                             Ident.: {ab.tag1}
                                             Total: {ab.total_dinheiro}
                                             String: {ab.st_full}
                                             Volume: {ab.total_litros}
                                             P.Unit : {ab.PU}
                                             Tempo: {ab.tempo}
                                             Bico: {ab.codbico}
                                             Data: {ab.datetime}
                                             Hora: {ab.datetime}
                                             Reg: {ab.registro}
                                             Enc.L. : {ab.encerranteI / ab.encerranteF}
                                             --------------------------------");
                }
                else
                    rchTxtBxLog.AppendText($"Erro na conexão com a concentradora no IP {_Connection.IP}. Tentando novamente...\r\n");

    I can return the connection, but when it arrives in the read (where it has a custom type) it returns the following message:

    "System.Runtime.InteropServices.MarshalDirectiveException: 'Signature of type of method is not compatible with PInvoke.'"

    Can someone help me?

    Friday, July 12, 2019 9:34 PM

All replies

  • What Pascal compiler are you using? You need to determine how DLLs created by that compiler can be used in Windows programs. I think the message you are getting implies that no Windows program could use the DLL.

    If the DLL can be used by Windows programs then please show us the relevant DLLImport you are using.



    Sam Hobbs
    SimpleSamples.Info

    Saturday, July 13, 2019 4:16 PM
  • Hi Gabriel,

    Thank you for posting here.

    Since this thread is related to pascal, it is a third-party product. We don't support it. I suggest that you could post in the following forum.

    https://csharpforums.net/forums/third-party-add-ins.26/

    The Visual C# forum discusses and asks questions about the C# programming language, IDE, libraries, samples, and tools.

    Note:This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. Microsoft does not control these sites and has not tested any software or information found on these sites; Therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, July 15, 2019 6:40 AM
  • The code you posted doesn't line up. 

    In your DllImport call the method is called `OpenSocket` in the `TesteExtracao` class. But the code you said isn't working is coming from `InicializaSocket2` on the `NativeMethods` class. You didn't post that definition. Furthermore the test class had a single parameter but the actual Pascal code you posted had 2 parameters. The `NativeMethods` version seems to have the correct # of arguments.

    Your Pascal code is using ANSI strings so you also need to include the `CharSet` on the `DllImport` to let .NET know you're working with ANSI strings.

    Moving on to the return type. You are trying to make a direct translation from Pascal to the corresponding .NET type and I don't believe them to be correct. You'll need to review them.

    1. Pascal booleans tend to be a single byte but it might vary by your compiler. If it doesn't work then use a single byte value instead.

    2. Pascal currency is defined to be a real type. It depends on the compiler but some will map it to a float or a double depending upon the processor. You'll need to figure out this mapping for your code and use either a `float` or a `double`. `decimal` is too large.

    3. Historically Pascal `integer` was +- 32K so this would map to 2 bytes so use a `short`.

    4. `char` in Pascal would be an ANSI char in C# so you'd need to set the CharSet to ANSI (I'd do this for the entire type).

    5. Your Pascal structure has fixed size arrays. You'll need to make your struct use arrays as well and you need to preallocate the arrays so the struct has the correct size that the Pascal code requires.

    6. `TDateTime` is a custom Pascal type. You'll need to define that strut as well. It likely won't map to a `DateTime`.


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, July 15, 2019 2:33 PM
  • "DateTime" and "string" are managed types.  They can't be marshaled to and from non-managed code.

    TDateTime in Borland's Delphi Pascal is a floating-point double.  You should be able to use "public double datetime".  You'll have to convert it to a C# DateTime value by hand.  And the character strings in your Pascal record aren't strings at all.  They are fixed-length character arrays.   although I BELIEVE in Delphi those are stored with a length byte followed by the characters.  So I think if you do something like this, you should get a lot closer.  Inter-language programming like this ALWAYS involved a lot of trial and error.

       {
            public bool value;
            public decimal total_dinheiro;
            public double total_litros;
            public decimal PU;
            public int tempo;
            public byte codbico_size;
            public char codbico[2];
            public int numbico;
            public int numtanque;
            public int voltanque;
            public int codcombustivel;
            public int seriecbc;
            public char tipocbc;
            public double datetime;
            public byte st_full_size;
            public char st_full[123];
            public int registro;
            public double encerranteI;
            public double encerranteF;
            public bool integridade;
            public bool checksum;
            public byte tag1_size;
            public char tag1[16];
            public byte tag2_size;
            public char tag2[16];
        }


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Tuesday, July 16, 2019 12:54 AM