Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Decimal to VB6 Currency

I have one C# DLL and one Visual Basic 6 DLL.

In C# there is a field x with data type Decimal. In VB6 there is a field y with data type Currency.

What would be the best way to pass x to y and back?

Currently I convert the fields to Double, but I am not sure if there are rounding implications.

Update 1:

Based on the helpful advice this is what my code looks now:

    public void FromVbToNet(long vb6curr)
    {
        decimal value = vb6curr / 10000;
    }

Problem is, when I try to call this from VB6 via interop, I get a compile error:

"Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic"

So how do I declare vb6curr? String, Object, Dynamic?

Update 2:

In case anyone needs this for reference, after further reading I came up with the following solution:

[return: MarshalAs(UnmanagedType.Currency)]
public decimal GetDecimalFromNetDll()
{
    decimal value = ... // Read from database
    return value;
}

public void SetDecimalInNetDll([MarshalAs(UnmanagedType.Currency)] decimal value)
{
    // Save to database
}

I call these from my unmanaged code in VB6 with a Currency parameter and everything seems to work so far.

like image 746
Luke Wage Avatar asked Dec 17 '14 09:12

Luke Wage


2 Answers

A VB6 Currency data type is stored as a 64 bit integer, implicitly scaled by 10,000. Armed with that knowledge it is straightforward to convert between that type and .net Decimal.

On the VB6 side you pass the data as Currency. On the C# side you pass it as long. Then on the C# side you scale by 10,000 to convert between your decimal value and the long value.

For example when you have a VB6 Currency value held in a C# long you convert to decimal like this:

long vb6curr = ...;
decimal value = vb6curr / 10000;

In the other direction it would be:

decimal value = ...;
long vb6curr = Convert.ToInt64(value*10000);
like image 145
David Heffernan Avatar answered Sep 21 '22 23:09

David Heffernan


After some reading I came up with this solution (see also under Update 2).

I had to marshal the Decimal type in .Net to the Currency type in the unmanaged VB6 code and vice versa.

[return: MarshalAs(UnmanagedType.Currency)]
public decimal GetDecimalFromNetDll()
{
    decimal value = ... // Read from database
    return value;
} 

public void SetDecimalInNetDll([MarshalAs(UnmanagedType.Currency)] decimal value)
{
    // Save to database
}

For detailed information see: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute%28v=vs.110%29.aspx

like image 26
Luke Wage Avatar answered Sep 19 '22 23:09

Luke Wage