Quote Originally Posted by fafalone View Post
Heh, "WHAT DO YOU MEAN THERE'S NO VarPtr()!??! How will I do ANYTHING!" --me, the first time I ever tried rewriting a project in VB.NET.
Haha. I feel you. VarPtr doesn't really fit into .Net all that well. For one thing, objects in .Net are not fixed in memory so you never want to allow programmers to just grab pointers all will-nilly. Another thing is that P/Invoke is very flexible. You have very fine control over how types are marshalled so you never need something like VarPtr when calling into an unmanaged environment like the Win32 API. You can just tell P/Invoke to marshal your parameters as pointers without needing to explicitly do it.

Just for fun, one can write their own VarPtr function if they are so inclined:-
Code:
Imports System.Data.OleDb
Imports System.Runtime.InteropServices

Module Module1

    <DllImport("kernel32.dll", EntryPoint:="RtlMoveMemory")>
    Public Sub CopyMemory(ByVal Destination As IntPtr, ByVal Source As IntPtr, ByVal Length As UInteger)
    End Sub

    Sub Main()

        'Unfortunately for this to work we MUST box primitive
        'value types assigning by them to an Object type variable
        'instead of Integer, otherwise VarPtr returns the address
        'to a copy of the value type. By boxing it, we make value types
        'behave like reference types so VarPtr will return the correct address
        Dim a As Object = 12I
        Dim b As Object = 200I

        CopyMemory(VarPtr(a), VarPtr(b), 4)

        'Prints 200 proving the copy operation worked
        Debug.WriteLine(a.ToString)
    End Sub

    'This cannot be made to work on value types so we use the Class
    'constraint to make sure the compiler only allows reference types are passed to VarPtr.
    'If we allow value types to be passed, VarPtr will always return the wrong address because
    'it would be returning the address of a copy, not the original. GCHandle.Alloc
    'is the culprit here as it's first parameter is passed by value. We cannot do anything about that.
    Private Function VarPtr(Of T As Class)(ByVal obj As T) As IntPtr
        Dim h = GCHandle.Alloc(obj, GCHandleType.Pinned)
        Try
            Return h.AddrOfPinnedObject
        Finally
            h.Free()
        End Try
    End Function


End Module
However, I'd recommend no VB.Net programmer ever do that EVER. While the above works it's a disaster waiting to happen. The GC can move those objects in memory at any time so there is potential for VarPtr to return an invalid address.

I think you might have preferred C# though. The C# compiler is far less constrained than the VB.Net compiler and it allows you to do low level programming very easily. The above code would look like this in C#:-
Code:
using System;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        unsafe
        {
            int a = 12;
            int b = 200;

            // Get the addresses of a and b
            int* aPtr = &a;
            int* bPtr = &b;

            // Copy the value of b to a
            *aPtr = *bPtr;

            // Prints 200 proving the copy operation worked
            Debug.WriteLine(a.ToString());
        }
    }
}
Quote Originally Posted by fafalone View Post
but there's virtually no beginner-friendly resources for the latter, any recommendations?
Hmmm..Let me see how best I can advise you here because I went though the same struggle. For years I tried to get a handle on assembly but nothing I ever found was beginner friendly enough. It wasn't until I stumbled on a specific article completely by accident did it really click for me. The article was about using the Flat assembler to compile ASM code into machine code and calling it from .Net as a function. To this day I'm not sure why this specific example made it click for me but I think it has something to do with the fact that it was within the context of an environment I was already familiar with, in this case .Net.

To that end, what I'd recommend is that you download trick's assembly VB6 add-in and start writing very simple functions in assembly and call them from VB6. This way it cuts out all the noise like setting up sections, import tables and all that. You can just jump right in and start with something very basic. Things will start clicking for you and you can then start learning more and more at your own pace. I've seen the kind of things you do, trust me, you would be a very capable assembly language programmer. You just need to stop letting it intimidate you.

I've been think about writing a very basic article on using assembly in VB6 or .Net. Nothing fancy, just something simple enough that anybody could start wetting their feet. I really do think it's possible for anyone to learn the basics but as you've said, it's really hard to find something that beginner friendly enough.