Using DLL from C#

  • Thread starter Thread starter Peter S.
  • Start date Start date
P

Peter S.

Hi everybody,

I'm trying to get access to a selfdeveloped DLL. What I did:

I created a new Classobject in C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ZufallArray
{
public class ZufallArray
{
[ExportDllAttribute.ExportDll("ZArray",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static int[] ZArray (int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl];
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j]= randObj.Next(beginn, ende);
}
return ZZahl;
}
}
}

I exported the function with "ExportDLL"
(http://www.codeproject.com/KB/dotnet/DllExport.aspx) and checked the result
with Dependency Walker.

I used the function with VBA (Excel):


Declare Function Zar Lib _
"C:\........\bin\Release\ZufallArray.dll" _
Alias "ZArray" (ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
As Integer()

Sub zarray()
Dim a() As Integer
a = Zar(10, 20, 3)
For i = 1 To UBound(a)
MsgBox a(i)
Next i
End Sub

Excel crashes! Why?

P.S.: I don't want to use the function by using a reference to .... .tlb and
than creating a new class in Excel (in this case the function must be defined
without "static). By the way this is working pretty good.

I want to use the function this way, because if this works, I can use the
function in other applications.

Peter
 
Hallo Peter,

I can not recreate your C# DLL file, but dit you register the DLL
file?

Wouter.
 
Hallo,

I did not! I don't like to register the DLL because I want to use this DLL
on other machines without a need of administration privileges.

It's not necessary to register the DLL (only possible with ActiveX) if you
use the function inside the DLL with "Declare function ...."

Peter
 
Peter
It might be worth trying something less ambitious than arrays initially.
What about using your dll just to add 2 numbers and return a double?

VBA uses the __stdcall calling convention rather than __cdecl, but that
should get you a bad calling convention error rather than a crash.

C ints are equivalent to VBA Longs, I suspect that same is true for C#
- that could cause a crash. (a,b,c should be long not integer)

I don't know how arrays are laid out in .net but I can imagine it being
different to C and to what VBA expects.

What specific error are you getting? (access violation?)

Cheers
Simon
Excel development website: www.codematic.net
 
Hallo Simon,

of course I already tried "an incremental approach" to my desired solution:

c#-Code:

[ExportDllAttribute.ExportDll("Summe")]
public static int Summe(int A, int B, [MarshalAs( UnmanagedType.AnsiBStr)]
ref string os)
{
os = A.ToString() + B.ToString() + " ok";
return A + B;
}

VBA-Code:

Private Declare Function Summe Lib "MyLib.dll" (ByVal A As Long, ByVal B As
Long, ByRef S As String) As Long

Sub test()
Dim S As String
i = Summe(10, 10, S)
MsgBox S
End Sub

Works fine!!!!!!! The string is given back perfectly.

Peter

Simon Murphy said:
Peter
It might be worth trying something less ambitious than arrays initially.
What about using your dll just to add 2 numbers and return a double?

VBA uses the __stdcall calling convention rather than __cdecl, but that
should get you a bad calling convention error rather than a crash.

C ints are equivalent to VBA Longs, I suspect that same is true for C#
- that could cause a crash. (a,b,c should be long not integer)

I don't know how arrays are laid out in .net but I can imagine it being
different to C and to what VBA expects.

What specific error are you getting? (access violation?)

Cheers
Simon
Excel development website: www.codematic.net

Hi everybody,

I'm trying to get access to a selfdeveloped DLL. What I did:

I created a new Classobject in C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ZufallArray
{
public class ZufallArray
{
[ExportDllAttribute.ExportDll("ZArray",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static int[] ZArray (int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl];
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j]= randObj.Next(beginn, ende);
}
return ZZahl;
}
}
}

I exported the function with "ExportDLL"
(http://www.codeproject.com/KB/dotnet/DllExport.aspx) and checked the result
with Dependency Walker.

I used the function with VBA (Excel):


Declare Function Zar Lib _
"C:\........\bin\Release\ZufallArray.dll" _
Alias "ZArray" (ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
As Integer()

Sub zarray()
Dim a() As Integer
a = Zar(10, 20, 3)
For i = 1 To UBound(a)
MsgBox a(i)
Next i
End Sub

Excel crashes! Why?

P.S.: I don't want to use the function by using a reference to .... .tlb and
than creating a new class in Excel (in this case the function must be defined
without "static). By the way this is working pretty good.

I want to use the function this way, because if this works, I can use the
function in other applications.

Peter
 
Did changing your VBA integers to longs help then?

Cheers
Simon
Excel development website: www.codematic.net

Hallo Simon,

of course I already tried "an incremental approach" to my desired solution:

c#-Code:

[ExportDllAttribute.ExportDll("Summe")]
public static int Summe(int A, int B, [MarshalAs( UnmanagedType.AnsiBStr)]
ref string os)
{
os = A.ToString() + B.ToString() + " ok";
return A + B;
}

VBA-Code:

Private Declare Function Summe Lib "MyLib.dll" (ByVal A As Long, ByVal B As
Long, ByRef S As String) As Long

Sub test()
Dim S As String
i = Summe(10, 10, S)
MsgBox S
End Sub

Works fine!!!!!!! The string is given back perfectly.

Peter

Simon Murphy said:
Peter
It might be worth trying something less ambitious than arrays initially.
What about using your dll just to add 2 numbers and return a double?

VBA uses the __stdcall calling convention rather than __cdecl, but that
should get you a bad calling convention error rather than a crash.

C ints are equivalent to VBA Longs, I suspect that same is true for C#
- that could cause a crash. (a,b,c should be long not integer)

I don't know how arrays are laid out in .net but I can imagine it being
different to C and to what VBA expects.

What specific error are you getting? (access violation?)

Cheers
Simon
Excel development website: www.codematic.net

Hi everybody,

I'm trying to get access to a selfdeveloped DLL. What I did:

I created a new Classobject in C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ZufallArray
{
public class ZufallArray
{
[ExportDllAttribute.ExportDll("ZArray",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static int[] ZArray (int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl];
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j]= randObj.Next(beginn, ende);
}
return ZZahl;
}
}
}

I exported the function with "ExportDLL"
(http://www.codeproject.com/KB/dotnet/DllExport.aspx) and checked the result
with Dependency Walker.

I used the function with VBA (Excel):


Declare Function Zar Lib _
"C:\........\bin\Release\ZufallArray.dll" _
Alias "ZArray" (ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
As Integer()

Sub zarray()
Dim a() As Integer
a = Zar(10, 20, 3)
For i = 1 To UBound(a)
MsgBox a(i)
Next i
End Sub

Excel crashes! Why?

P.S.: I don't want to use the function by using a reference to .... .tlb and
than creating a new class in Excel (in this case the function must be defined
without "static). By the way this is working pretty good.

I want to use the function this way, because if this works, I can use the
function in other applications.

Peter
 
No! I tried every combination (all integer, all long, some interger and some
long etc).

Peter

Simon Murphy said:
Did changing your VBA integers to longs help then?

Cheers
Simon
Excel development website: www.codematic.net

Hallo Simon,

of course I already tried "an incremental approach" to my desired solution:

c#-Code:

[ExportDllAttribute.ExportDll("Summe")]
public static int Summe(int A, int B, [MarshalAs( UnmanagedType.AnsiBStr)]
ref string os)
{
os = A.ToString() + B.ToString() + " ok";
return A + B;
}

VBA-Code:

Private Declare Function Summe Lib "MyLib.dll" (ByVal A As Long, ByVal B As
Long, ByRef S As String) As Long

Sub test()
Dim S As String
i = Summe(10, 10, S)
MsgBox S
End Sub

Works fine!!!!!!! The string is given back perfectly.

Peter

Simon Murphy said:
Peter
It might be worth trying something less ambitious than arrays initially.
What about using your dll just to add 2 numbers and return a double?

VBA uses the __stdcall calling convention rather than __cdecl, but that
should get you a bad calling convention error rather than a crash.

C ints are equivalent to VBA Longs, I suspect that same is true for C#
- that could cause a crash. (a,b,c should be long not integer)

I don't know how arrays are laid out in .net but I can imagine it being
different to C and to what VBA expects.

What specific error are you getting? (access violation?)

Cheers
Simon
Excel development website: www.codematic.net


Peter S. wrote:
Hi everybody,

I'm trying to get access to a selfdeveloped DLL. What I did:

I created a new Classobject in C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ZufallArray
{
public class ZufallArray
{
[ExportDllAttribute.ExportDll("ZArray",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static int[] ZArray (int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl];
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j]= randObj.Next(beginn, ende);
}
return ZZahl;
}
}
}

I exported the function with "ExportDLL"
(http://www.codeproject.com/KB/dotnet/DllExport.aspx) and checked the result
with Dependency Walker.

I used the function with VBA (Excel):


Declare Function Zar Lib _
"C:\........\bin\Release\ZufallArray.dll" _
Alias "ZArray" (ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
As Integer()

Sub zarray()
Dim a() As Integer
a = Zar(10, 20, 3)
For i = 1 To UBound(a)
MsgBox a(i)
Next i
End Sub

Excel crashes! Why?

P.S.: I don't want to use the function by using a reference to .... .tlb and
than creating a new class in Excel (in this case the function must be defined
without "static). By the way this is working pretty good.

I want to use the function this way, because if this works, I can use the
function in other applications.

Peter
 
Peter
Did you try passing the array as a variant?

Or maybe passing the array in by ref from VB as a parameter and just
populate the array in C#?

Cheers
Simon
Excel development website: www.codematic.net

No! I tried every combination (all integer, all long, some interger and some
long etc).

Peter

Simon Murphy said:
Did changing your VBA integers to longs help then?

Cheers
Simon
Excel development website: www.codematic.net

Hallo Simon,

of course I already tried "an incremental approach" to my desired solution:

c#-Code:

[ExportDllAttribute.ExportDll("Summe")]
public static int Summe(int A, int B, [MarshalAs( UnmanagedType.AnsiBStr)]
ref string os)
{
os = A.ToString() + B.ToString() + " ok";
return A + B;
}

VBA-Code:

Private Declare Function Summe Lib "MyLib.dll" (ByVal A As Long, ByVal B As
Long, ByRef S As String) As Long

Sub test()
Dim S As String
i = Summe(10, 10, S)
MsgBox S
End Sub

Works fine!!!!!!! The string is given back perfectly.

Peter

:

Peter
It might be worth trying something less ambitious than arrays initially.
What about using your dll just to add 2 numbers and return a double?

VBA uses the __stdcall calling convention rather than __cdecl, but that
should get you a bad calling convention error rather than a crash.

C ints are equivalent to VBA Longs, I suspect that same is true for C#
- that could cause a crash. (a,b,c should be long not integer)

I don't know how arrays are laid out in .net but I can imagine it being
different to C and to what VBA expects.

What specific error are you getting? (access violation?)

Cheers
Simon
Excel development website: www.codematic.net


Peter S. wrote:
Hi everybody,

I'm trying to get access to a selfdeveloped DLL. What I did:

I created a new Classobject in C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ZufallArray
{
public class ZufallArray
{
[ExportDllAttribute.ExportDll("ZArray",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static int[] ZArray (int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl];
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j]= randObj.Next(beginn, ende);
}
return ZZahl;
}
}
}

I exported the function with "ExportDLL"
(http://www.codeproject.com/KB/dotnet/DllExport.aspx) and checked the result
with Dependency Walker.

I used the function with VBA (Excel):


Declare Function Zar Lib _
"C:\........\bin\Release\ZufallArray.dll" _
Alias "ZArray" (ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)
As Integer()

Sub zarray()
Dim a() As Integer
a = Zar(10, 20, 3)
For i = 1 To UBound(a)
MsgBox a(i)
Next i
End Sub

Excel crashes! Why?

P.S.: I don't want to use the function by using a reference to .... .tlb and
than creating a new class in Excel (in this case the function must be defined
without "static). By the way this is working pretty good.

I want to use the function this way, because if this works, I can use the
function in other applications.

Peter
 
Hi Peter,

I have recreated yout problem.
I have tried to create a log-file from the DLL, but dit not succeed in
this.

Why are you ussing the DLL.
Have you considered creating this fucntion in a separate module in
your Excel file and export it.
You can import it in other Excel File which need the same function.

Option Explicit
Option Base 1

Public Function FilledArray(intBegin As Integer, _
intEnde As Integer, _
intAnzahl As Integer) As Variant
ReDim intArray(intAnzahl) As Integer
Dim intWiederholung As Integer

Randomize Timer
For intWiederholung = 0 To intAnzahl - 1
intArray(intWiederholung) = intBegin + _
Fix(Rnd() * (intEnde - intBegin))
Next

FilledArray = intArray
End Function

HTH,
Wouter
 
Hi,

thanks a lot for your coding! Why didn't I do that in the way you show? I
use Unify Gupta SQLBase which is a very stable database, but it's a little
bit tricky to use some function there. A function to get random numbers is
not available there. So I have to code a function (C#, C++, VB6 etc.) and
store it in a DLL. If I can use the function in VBA by "Declare function
......." I can use it in SQLBase.

In the meantime I got the result:

Code in C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;

namespace classtest
{
public class test
{
[ExportDllAttribute.ExportDll("ArrayTest",
System.Runtime.InteropServices.CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType =
VarEnum.VT_I4)]
public static int[] ArrayTest(int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl+1];
Random randObj = new Random();
for (int j = 0; j < ZZahl.Length; j++)
{
ZZahl[j] = randObj.Next(beginn, ende);
}
return ZZahl;
}
}
}

I exported the function with "ExportDLL"
(http://www.codeproject.com/KB/dotnet/DllExport.aspx) and checked the result
with Dependency Walker.

I used the function with VBA (Excel):

Private Declare Function classTArray Lib _
"C:\........\bin\Release\classtarray.dll" _
Alias "ArrayTest" (ByVal nAnfang As Long, ByVal nEnde As Long, ByVal nAnzahl
As Long) As Long()

Sub test()
Dim x() As Long
x = classTArray(0, 100, 10)
For i = 0 To 10
MsgBox x(i)
Next i
End Sub

Works fine!

Peter
 
Back
Top