Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

How to Create a VB Netduino DLL with CIL/IL


  • Please log in to reply
2 replies to this topic

#1 baxter

baxter

    Advanced Member

  • Members
  • PipPipPip
  • 415 posts

Posted 02 January 2012 - 02:00 AM

Visual Basic 2010 Express 2010 does not offer a Class Library option for the .NEt Micro Framework. The attached files show how to do this using CIL/IL. It is also partly an answer to a previous post, "How to Deploy IL to Netduino?" I don't think there is any way to to do this with raw CIL/IL. The attached files employ a brute force BAT file approach and could probably be automated via the System.Diagnostics process class.

The steps are outlined in Instructions.Pdf. The Dll is generated as a Vb Windows Class Library. The DLL is then disassembled via Ildam to get the IL. This IL is then edited to conform to the Micro Framework. It is reassembled to a DLL and then processed for Netduino using MetaDataProcessor.exe. Theoretically, you could code in your favorite CLI language (e.g. F#)and do the same thing.

To see the requirements for a Micro Framework DLL, Write one in the C# Micro Framework Template and dissamble it with Ildasm. Here is Luke Commings' Bitconverter that I converted to a DLL in C# and disassembled,
//  Microsoft (R) .NET Framework IL Disassembler.  Version 3.5.30729.1
//  Copyright (c) Microsoft Corporation.  All rights reserved.

// N.B. ******************** Ignore this *****************
// warning : THIS IS A PARTIAL DISASSEMBLY, NOT SUITABLE FOR RE-ASSEMBLING

// Only shown items having accessibility: Public

// Classes defined in this module:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class BitConverter                   (public) (abstract) (auto) (ansi) (sealed) 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .ver 4:2:0:0
}
.assembly extern Microsoft.SPOT.Native
{
  .ver 4:2:0:0
}
.assembly Bitconverter1
{
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
.module Bitconverter1.dll
// MVID: {591A8669-F2EC-422F-A8D5-C0BFA8B82A9D}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x00A40000


// =============== CLASS MEMBERS DECLARATION ===================

.class public abstract auto ansi sealed beforefieldinit Bitconverter1.BitConverter
       extends [mscorlib]System.Object
{
  .method public hidebysig static void  ToBytes(uint8[] buffer,
                                                int32 offset,
                                                int64 'value') cil managed
  {
    // Code size       26 (0x1a)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  ldarg.1
    IL_0002:  ldc.i4.4
    IL_0003:  ldarg.2
    IL_0004:  ldc.i4.s   32
    IL_0006:  shr
    IL_0007:  conv.u4
    IL_0008:  call       void [Microsoft.SPOT.Native]Microsoft.SPOT.Hardware.Utility::InsertValueIntoArray(uint8[],
                                                                                                           int32,
                                                                                                           int32,
                                                                                                           uint32)
    IL_000d:  ldarg.0
    IL_000e:  ldarg.1
    IL_000f:  ldc.i4.4
    IL_0010:  add
    IL_0011:  ldc.i4.4
    IL_0012:  ldarg.2
    IL_0013:  conv.u4
    IL_0014:  call       void [Microsoft.SPOT.Native]Microsoft.SPOT.Hardware.Utility::InsertValueIntoArray(uint8[],
                                                                                                           int32,
                                                                                                           int32,
                                                                                                           uint32)
    IL_0019:  ret
  } // end of method BitConverter::ToBytes

  .method public hidebysig static void  ToBytes(uint8[] buffer,
                                                int32 offset,
                                                float32 'value') cil managed
  {
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  ldarg.1
    IL_0002:  ldc.i4.4
    IL_0003:  ldarga.s   'value'
    IL_0005:  conv.u
    IL_0006:  ldind.u4
    IL_0007:  call       void [Microsoft.SPOT.Native]Microsoft.SPOT.Hardware.Utility::InsertValueIntoArray(uint8[],
                                                                                                           int32,
                                                                                                           int32,
                                                                                                           uint32)
    IL_000c:  ret
  } // end of method BitConverter::ToBytes

 ----- Cut for brevity -------

Here are the important entries,

// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.ver 4:2:0:0
}
.assembly extern Microsoft.SPOT.Native
{
.ver 4:2:0:0
}

Note that they target the Micro Framework. I don't know how Ilasm resolves the correct target framework.

The first question will be; Why bother with this since C# has this capability for the Micro Framework? Well, some prefer VB coding, but mostly it is an exploration into the wonderful world of Ilasm, Ildasm and CIL. No one writes IL from scratch except textbook authors trying to explain it.

Baxter

Attached Files



#2 Bainesbunch

Bainesbunch

    Advanced Member

  • Members
  • PipPipPip
  • 61 posts
  • LocationFrance

Posted 17 January 2012 - 08:24 PM

Hi Baxter,

Can this not simply be done by setting the application Type in the Netduino project properties in a c# or vb project to "Class library" this will then create a DLL that can be used for the MF, you need to be sure you are targeting the correct .NET version.


The steps I use

  • Right click in the solution explorer on the Netduino project name and select Properties (alt+Enter)
  • In the application Tab go to the dropdown for the application type and select "Class Library"
  • Build the application
  • Now go and look in the "bin" folder under the source folder and then into either "debug" or "release" folder depending on your build
  • This is your DLL. It is best left here and referenced from your project. If you want to move it into your new project folder then I suggest you create a folder called LIBS and copy ALL THREE items the DLL and the two folders that are with it called "be" and "le" you do not need the .PDB file.

I often use libraries that are in the public domain but written in c# i compile them into DLLs and then reference them in my VB application. this can be useful if you only want part of a public library. You can remove the stuff you don’t want and then only compile the bits that you need. This is useful if memory is getting short.


Cheers Pete.
I was going to change the world, then I discovered Netduino.
The world will have to wait.

#3 baxter

baxter

    Advanced Member

  • Members
  • PipPipPip
  • 415 posts

Posted 18 January 2012 - 06:15 AM

Can this not simply be done by setting the application Type in the Netduino project properties in a c# or vb project to "Class library" this will then create a DLL that can be used for the MF, you need to be sure you are targeting the correct .NET version.

Hi Pete,

Thanks for the suggestions. I completely overlooked the Class Library Application type in VB Express. I usually use C# Express to create a class library and then just reference it in a VB Project. My post was mostly an academic exercise in MSIL/CIL/IL. I wanted to see how unsafe code was handled under the hood. I was also on a quest to create a c style union which is very useful to convert a single to bytes.
'VB Windows Code
Imports System
Imports System.Runtime.InteropServices
Module Module1
    Sub Main()
        Dim union As SampleUnion = New SampleUnion
        union.FloatValue = 1234.567
        Dim a As UInteger = union.IntValue
        Debug.Print("intValue = " & a.ToString) ' intValue = 1150964261
        union.IntValue = 1150964261
        Dim b As Single = union.FloatValue
        Debug.Print("floatValue = " & b.ToString) ' floatValue = 1234.567
        'Structure SampleUnion Values
        '============================
        'ByteValue0 = 37
        'ByteValue1 = 82
        'ByteValue2 = 154
        'ByteValue3 = 68
        'FloatValue = 1234.567
        'IntValue = 1150964261
        System.Console.ReadLine()
    End Sub
    <StructLayout(LayoutKind.Explicit)> _
    Public Structure SampleUnion
        <FieldOffset(0)> Public FloatValue As Single
        <FieldOffset(0)> Public IntValue As UInteger
        <FieldOffset(0)> Public ByteValue0 As Byte
        <FieldOffset(1)> Public ByteValue1 As Byte
        <FieldOffset(2)> Public ByteValue2 As Byte
        <FieldOffset(3)> Public ByteValue3 As Byte
    End Structure

End Module
Unfortunately, the MF does not support the FieldOffset attribute. I thought I could modify the underlying CIL to make it work, but not with much success. I have since moved on to more productive things.

Baxter




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.