Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. Unmanaged DLLs

Unmanaged DLLs

Scheduled Pinned Locked Moved Visual Basic
helpcsharpc++visual-studio
5 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    Charles Keepax
    wrote on last edited by
    #1

    Hi, I have a mostly C++ background and have a small VB.NET problem and was hoping for some advice from you guru's out there in VB land. I am using VS.NET 2002, incase anyone know of a problem with that version. I am trying to access functions in a unmanaged DLL from a managed VB application. I can get this to work fine until I use a DLL function that has a string as a parameter. When I call a function with a string as a parameter, although the DLL receives the string correcly, the return value of all future DLL calls is garbage. I have created a small sample application (DLL and VB) to demonstrate the problem. I have posted the code in this post (sorry about that but figured it would be nessecary). Any help would be awesome? Thanks in Advance, Charles Example follows, in the VB application the first two calls to fnTestNumber are handled fine, but the return value from fnTestString and the last fnTestNumber are random. VB Application: Imports System.Runtime.InteropServices Module Module1 <DllImport("TestDLL.DLL", _ CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _ Function fnTestNumber(ByVal iTest As Long) As Long End Function <DllImport("TestDLL.DLL", _ CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _ Function fnTestString(<MarshalAs(UnmanagedType.LPStr)> ByVal szTest As String) As Long End Function Sub Main() Dim retcode As Long retcode = fnTestNumber(9876) retcode = fnTestNumber(7654) retcode = fnTestString("DATAFILE1.DAT") retcode = fnTestNumber(1234) End Sub End Module C++ DLL: __declspec(dllexport) int fnTestNumber(int iTest) { return iTest; } __declspec(dllexport) int fnTestString(const char* szTest) { return 42; }

    L D 2 Replies Last reply
    0
    • C Charles Keepax

      Hi, I have a mostly C++ background and have a small VB.NET problem and was hoping for some advice from you guru's out there in VB land. I am using VS.NET 2002, incase anyone know of a problem with that version. I am trying to access functions in a unmanaged DLL from a managed VB application. I can get this to work fine until I use a DLL function that has a string as a parameter. When I call a function with a string as a parameter, although the DLL receives the string correcly, the return value of all future DLL calls is garbage. I have created a small sample application (DLL and VB) to demonstrate the problem. I have posted the code in this post (sorry about that but figured it would be nessecary). Any help would be awesome? Thanks in Advance, Charles Example follows, in the VB application the first two calls to fnTestNumber are handled fine, but the return value from fnTestString and the last fnTestNumber are random. VB Application: Imports System.Runtime.InteropServices Module Module1 <DllImport("TestDLL.DLL", _ CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _ Function fnTestNumber(ByVal iTest As Long) As Long End Function <DllImport("TestDLL.DLL", _ CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _ Function fnTestString(<MarshalAs(UnmanagedType.LPStr)> ByVal szTest As String) As Long End Function Sub Main() Dim retcode As Long retcode = fnTestNumber(9876) retcode = fnTestNumber(7654) retcode = fnTestString("DATAFILE1.DAT") retcode = fnTestNumber(1234) End Sub End Module C++ DLL: __declspec(dllexport) int fnTestNumber(int iTest) { return iTest; } __declspec(dllexport) int fnTestString(const char* szTest) { return 42; }

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      Hi, I am used to use P/Invoke between managed C# and native C, here are some suggestions: - passing a read-only string from managed to unmanaged works fine, it does not even need MarshalAs(UnmanagedType.LPStr - by default managed strings are Unicode and get marshaled as 16-bit char collections; adding CharSet:=CharSet.Ansi should fix that were appropriate. - I avoid returning a string, since that would mean the unmanaged world needs to create an object that can continue to exist in the managed world; instead: - when needing a string result, I tend to pass a StringBuilder object, with its initial capacity appropriately set, and also pass that capacity; then the unmanaged world can treat it as a char buffer of specified length. - always: your calling conventions must match; since I fail to remember the default, I always make it explicit on both sides. - most things you do wrong in P/Invoke result in an exception, quite often corresponding to an access violation. Hope this helps.

      Luc Pattyn [Forum Guidelines] [My Articles]


      This month's tips: - before you ask a question here, search CodeProject, then Google; - the quality and detail of your question reflects on the effectiveness of the help you are likely to get; - use PRE tags to preserve formatting when showing multi-line code snippets.


      1 Reply Last reply
      0
      • C Charles Keepax

        Hi, I have a mostly C++ background and have a small VB.NET problem and was hoping for some advice from you guru's out there in VB land. I am using VS.NET 2002, incase anyone know of a problem with that version. I am trying to access functions in a unmanaged DLL from a managed VB application. I can get this to work fine until I use a DLL function that has a string as a parameter. When I call a function with a string as a parameter, although the DLL receives the string correcly, the return value of all future DLL calls is garbage. I have created a small sample application (DLL and VB) to demonstrate the problem. I have posted the code in this post (sorry about that but figured it would be nessecary). Any help would be awesome? Thanks in Advance, Charles Example follows, in the VB application the first two calls to fnTestNumber are handled fine, but the return value from fnTestString and the last fnTestNumber are random. VB Application: Imports System.Runtime.InteropServices Module Module1 <DllImport("TestDLL.DLL", _ CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _ Function fnTestNumber(ByVal iTest As Long) As Long End Function <DllImport("TestDLL.DLL", _ CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _ Function fnTestString(<MarshalAs(UnmanagedType.LPStr)> ByVal szTest As String) As Long End Function Sub Main() Dim retcode As Long retcode = fnTestNumber(9876) retcode = fnTestNumber(7654) retcode = fnTestString("DATAFILE1.DAT") retcode = fnTestNumber(1234) End Sub End Module C++ DLL: __declspec(dllexport) int fnTestNumber(int iTest) { return iTest; } __declspec(dllexport) int fnTestString(const char* szTest) { return 42; }

        D Offline
        D Offline
        Dave Kreskowiak
        wrote on last edited by
        #3

        In addition to what Luc said, you're using and returning 32-bit numbers in/from your C++ functions, but your VB.NET declarations are Longs. The Long type in VB.NET is a 64-bit signed integer. I think you're actually looking for the Integer type, which is 32-bit signed.

        <DllImport("TestDLL.DLL", _
        CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
        Function fnTestNumber(ByVal iTest As Integer) As Integer
        End Function
        <DllImport("TestDLL.DLL", _
        CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
        Function fnTestString(ByVal szTest As String) As Integer
        End Function

        A guide to posting questions on CodeProject[^]
        Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
             2006, 2007

        L C 2 Replies Last reply
        0
        • D Dave Kreskowiak

          In addition to what Luc said, you're using and returning 32-bit numbers in/from your C++ functions, but your VB.NET declarations are Longs. The Long type in VB.NET is a 64-bit signed integer. I think you're actually looking for the Integer type, which is 32-bit signed.

          <DllImport("TestDLL.DLL", _
          CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
          Function fnTestNumber(ByVal iTest As Integer) As Integer
          End Function
          <DllImport("TestDLL.DLL", _
          CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
          Function fnTestString(ByVal szTest As String) As Integer
          End Function

          A guide to posting questions on CodeProject[^]
          Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
               2006, 2007

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          Right. I missed that one, although I have made similar mistakes myself. :)

          Luc Pattyn [Forum Guidelines] [My Articles]


          This month's tips: - before you ask a question here, search CodeProject, then Google; - the quality and detail of your question reflects on the effectiveness of the help you are likely to get; - use PRE tags to preserve formatting when showing multi-line code snippets.


          modified on Tuesday, January 15, 2008 1:41:17 PM

          1 Reply Last reply
          0
          • D Dave Kreskowiak

            In addition to what Luc said, you're using and returning 32-bit numbers in/from your C++ functions, but your VB.NET declarations are Longs. The Long type in VB.NET is a 64-bit signed integer. I think you're actually looking for the Integer type, which is 32-bit signed.

            <DllImport("TestDLL.DLL", _
            CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
            Function fnTestNumber(ByVal iTest As Integer) As Integer
            End Function
            <DllImport("TestDLL.DLL", _
            CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl)> _
            Function fnTestString(ByVal szTest As String) As Integer
            End Function

            A guide to posting questions on CodeProject[^]
            Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
                 2006, 2007

            C Offline
            C Offline
            Charles Keepax
            wrote on last edited by
            #5

            Ah...... I knew it would be something really annoyingly simple. Thank you both very much for the help. You have no idea the hours of frustration that saved me. Thanks again, Charles

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups