Access Violation Exception

Windows specific questions.
Post Reply
CharlesExum
Posts: 4
Joined: Apr 07, 2017 13:38

Access Violation Exception

Post by CharlesExum »

Hi! I've got a weird situation going on over here where I need to get part of a .net project onto unmanaged code.

After compiling a .dll, I am able to return simple things like integers inside .net, but, getting the .dll to do work on an array of bytes is throwing Access Violation exception. Can someone enlighten me a little bit, without "doing my homework" so to speak.

c# stuff :)

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace CSharpDLLTestConsole
{
    public class TestConsole
    {
        [DllImport("Olis8453.dll")]
        public static extern int Increment(int x);

        [DllImport("Olis8453.dll")]
        public static extern void ProcessRawData(int size, byte[] data);

       
        static void Main(string[] args)
        {
            int iAddToMe = 0;//counter
            for (int x = 0; x < 10; x++)
            {
                iAddToMe = Increment(iAddToMe); //makes this call just fine
                Console.WriteLine(iAddToMe);
            }

            int iArraySize = 100;
            byte[] barrTestData = new byte[iArraySize];
            ProcessRawData(iArraySize, barrTestData); //Access Violation...
            foreach (byte i in barrTestData)
            {
                Console.WriteLine(i);
            }
            string wait = Console.ReadLine();
        }
    }
}
and the .dll

Code: Select all

'Date: 2017.03.20
'Author: Charles DeGrapharee Exum

'A .dll which houses Interpret, and data deconvolution functions for OWAD.


Extern "Windows-MS"
Public Dim iArraySize As Integer = 1100

Public Function Increment (ByVal a As Integer) As Integer Export 'test function
    Dim iNumber as Integer
    iNumber = a + 1
    Return iNumber
End Function

Public Sub ProcessRawData (ByVal iarrsize As Integer, scandata() As UByte) Export
    '1) assign incomingdata to a local byte array
    '2) cast to double array
    '3) do math on each point
    '4) cast back to byte array
    '5) outgoingdata == incomingdata
    
    'dynamically calculate the size of the data set and initialize the data arrays
   
    Dim iArraySize As Integer = iarrsize 
    Dim barrIncomingData(iArraySize) As Byte     
    
    'assign incomingdata byte array to a local member
    For c As Integer = 0 to iArraySize
        'barrIncomingData(c) = scandata(c)
        scandata(c) = 1
        Print scandata(c)
    Next c
    
    

End Sub

End Extern


vdecampo
Posts: 2992
Joined: Aug 07, 2007 23:20
Location: Maryland, USA
Contact:

Re: Access Violation Exception

Post by vdecampo »

You need to pin the byte array and marshal it to a fixed memory buffer.

Example

Code: Select all

IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call unmanaged code
Marshal.FreeHGlobal(unmanagedPointer);
Then you need to copy the result back to the array.

-Vince
CharlesExum
Posts: 4
Joined: Apr 07, 2017 13:38

Re: Access Violation Exception

Post by CharlesExum »

Thank you!
CharlesExum
Posts: 4
Joined: Apr 07, 2017 13:38

Re: Access Violation Exception

Post by CharlesExum »

Hey again. This way worked too, using some pointers. It got around all the data marshaling stuff in .NET. Would you mind giving some feedback?

Code: Select all


Public Sub CopyArray(pbarrSource As Byte Ptr, pbarrDest As Byte Ptr, elements As Long) Export'test function to copy memory from one location to another    
    Dim i As Long
    Dim iLength As Long = elements - 1
    For i = 0 To iLength    
    *(pbarrDest + i) = *(pbarrSource + i)
    Next i
End Sub

SARG
Posts: 1765
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Access Violation Exception

Post by SARG »

No need extra variables.

Code: Select all

Public Sub CopyArray(pbarrSource As Byte Ptr, pbarrDest As Byte Ptr, elements As Long) Export'test function to copy memory from one location to another    
    For i as long = 0 To elements - 1   
    *(pbarrDest + i) = *(pbarrSource + i)
    Next i
End Sub
CharlesExum
Posts: 4
Joined: Apr 07, 2017 13:38

Re: Access Violation Exception

Post by CharlesExum »

These are some pointer functions which cast arrays of unsigned bytes to various other type arrays.

freeBasic:

Code: Select all

               /'
Date: 2017.03.20
Author: Charles DeGrapharee Exum
Purpose: To create an unmanaged .dll which casts byte arrays into other types.
'/' 

#include "crt/math.bi"

Extern "Windows-MS"

Public Function Increment(ByVal a As Long) As Long Export 'test function
    Dim iNumber as Long
    iNumber = a + 1
    Return iNumber
End Function

Public Sub CopySBytes(pbarrSource As Byte Ptr, pbarrDest As Byte Ptr, elements As ULong) Export'test function to copy memory from one location to another    
    
    For i As ULong = 0 To elements - 1    
        *(pbarrDest + i) = *(pbarrSource + i)
    Next i

End Sub

Public Sub CopyMemory(pbarrSource As UByte Ptr, pbarrDest As UByte Ptr, elements As ULong) Export'test function to copy memory from one location to another    
    
    For i As ULong = 0 To elements - 1    
        *(pbarrDest + i) = *(pbarrSource + i)
    Next i

End Sub

Public Sub ReturnDoubleArray(pbarrSource As UByte Ptr, pdarrDest As Double Ptr, elements As ULong) Export
    Dim iTemp As Ulong = 0
    Dim b As UByte = 0
    Dim barrTempDatum(4) As Ubyte
    Dim barrTemp(elements) As UByte
    Dim iarrTemp(elements / 4) As ULong
    Dim dTemp As Double
    Dim darrTemp(elements / 4) As Double '**the double is 64-bit, so there are secretly 2x ubytes here
    
    'create a local UByte array from the source pointer
    For c As ULong = 0 To elements - 1 Step 1
        b = *(pbarrSource + c)
        barrTemp(c) = b        
    Next c 
    
    'create a local ULong array
    For d As ULong = 0 To elements - 1 Step 4
        'get the ubytes
        barrTempDatum(0) = barrTemp(d)
        barrTempDatum(1) = barrTemp(d + 1)
        barrTempDatum(2) = barrTemp(d + 2)
        barrTempDatum(3) = barrTemp(d + 3)
        'bit shift
        barrTempDatum(0) = barrTempDatum(0) SHL 24
        barrTempDatum(1) = barrTempDatum(1) SHL 16
        barrTempDatum(2) = barrTempDatum(2) SHL 8
        barrTempDatum(3) = barrTempDatum(3) SHL 0
        'return ulong
        iTemp = barrTempDatum(0) + barrTempDatum(1) + barrTempDatum(2) + barrTempDatum(3)
        'store in ulong()
        iarrTemp(d / 4) = iTemp
        'iarrTemp(d / 4) = Return32BitDatum(barrTempDatum())
        'Print "iarrTemp(d / 4) " & " " & (d / 4) & " " & iarrTemp(d / 4) 
        'For e As ULong = 0 To 3 Step 1
        '    barrTempDatum(e) = 0
        'Next e                
    Next d
    
    'create a local double array -- seems like an extra step, but I secretly need to do math here later on
    'copy the memory back to caller via pointer
    For a As ULong = 0 To (elements / 4) - 1 Step 1
        'local double()
        'dTemp = CDbl(iarrTemp(a))        
        'store in local double()
        'darrTemp(a) = dTemp       
        
        darrTemp(a) = iarrTemp(a)
        print darrTemp(a)
    Next a
    
    'copy the memory back to caller via pointer
    For a As Ulong = 0 To (elements / 4) - 1 Step 1
        *(pdarrDest + a) = darrTemp(a)
    Next a
    
End Sub

Public Sub ReturnULongArray(pbarrSource As UByte Ptr, piarrDest As ULong Ptr, elements As ULong) Export
    Dim i As Ulong = 0
    Dim b As UByte = 0
    Dim barrTempDatum(4) As Ubyte
    Dim barrTemp(elements) As UByte
    Dim iarrTemp(elements / 4) As ULong    
    
    'create a local UByte array from the source pointer
    For c As ULong = 0 To elements - 1 Step 1
        b = *(pbarrSource + c)
        barrTemp(c) = b        
    Next c    
    'create a local ULong array
    For d As ULong = 0 To elements - 1 Step 4
        'get the ubytes
        barrTempDatum(0) = barrTemp(d)
        barrTempDatum(1) = barrTemp(d + 1)
        barrTempDatum(2) = barrTemp(d + 2)
        barrTempDatum(3) = barrTemp(d + 3)
        'bit shift
        barrTempDatum(0) = barrTempDatum(0) SHL 24
        barrTempDatum(1) = barrTempDatum(1) SHL 16
        barrTempDatum(2) = barrTempDatum(2) SHL 8
        barrTempDatum(3) = barrTempDatum(3) SHL 0
        'return ulong
        i = barrTempDatum(0) + barrTempDatum(1) + barrTempDatum(2) + barrTempDatum(3)
        iarrTemp(d / 4) = i
        'iarrTemp(d / 4) = Return32BitDatum(barrTempDatum())
        'Print "iarrTemp(d / 4) " & " " & (d / 4) & " " & iarrTemp(d / 4) 
        For e As ULong = 0 To 3 Step 1
            barrTempDatum(e) = 0
        Next e
                
    Next d
    
    'populate destination array via ulong pointer
    For e As Ulong = 0 To (elements / 4) - 1 Step 1
        *(piarrDest + e) = iarrTemp(e)
    Next e
    
End Sub

End Extern
C# linker for .net

Code: Select all

using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System;

namespace DynamicLinkerProof
{
    public static unsafe class DynamicLinker
    {
        [DllImport("BitConversionUtilities.dll")]
        public static extern int Increment(int x);       

        [DllImport("BitConversionUtilities.dll", CallingConvention = CallingConvention.StdCall)]
        public unsafe static extern void CopyArray(byte* s, byte* d, Int32 l);

        [DllImport("BitConversionUtilities.dll", CallingConvention = CallingConvention.StdCall)]
        public unsafe static extern void ReturnULongArray(byte* s, UInt32* d, UInt32 l);

        [DllImport("BitConversionUtilities.dll", CallingConvention = CallingConvention.StdCall)]
        public unsafe static extern void ReturnDoubleArray(byte* s, double* d, UInt32 l); 
    }
}
Post Reply