Solved

Using VS2005 I am writing a C++ Class to be used by VB.NET. It seems that I can't pass pointers

Posted on 2006-11-30
11
449 Views
Last Modified: 2012-06-27
I am trying to write a C++ class that I can use in VB.NET. The final product will beusing a LIB file that I don't have the source so I need to "wrap" it with C++. I can make simple data types work (ie int, douoble, char) but I can't make arrays or pointers work. I am a VB programmer by nature and I have a simple knowledge of C++ programming. I use the VisuallC++ CLR Class Library as a starting point. I was able to make the simple data parameters work. However when I try to add a pointer to a char array the sub does not show up on my list when I reference the DLL and if I force the issue I get the error "'DoIt" has a return type that is not supported or parameter types that are not suppoter".
I have included the code below
Can anyone tell me how I can make a C++ DLL that will fill an array?

---------MathFunc2dll.h------------
// MathFuncs2dll.h

#pragma once
#include <string>

using namespace System;

namespace MathFuncs2dll {

      public ref class MyMathFuncs
      {
      public:
            double Add2(double a, double b);
            double Subtract(double a, double b);
            double Multiply(double a, double b);
            double Divide(double a, double b);
            void DoIt(char *Buffer);
      };
}

---------MathFunc2dll.cpp------------
// This is the main DLL file.

#include "stdafx.h"
#include <string>
#include "MathFuncs2dll.h"

namespace MathFuncs2dll
{
      double MyMathFuncs::Add2(double a, double b)
      {
            return a+b;
      }
      double MyMathFuncs::Subtract(double a, double b)
      {
            return a-b;
      }
      double MyMathFuncs::Multiply(double a, double b)
      {
            return a*b;
      }
      double MyMathFuncs::Divide(double a, double b)
      {
            if (b==0) {
                  return 0;
            }

            return a/b;
      }
      void MyMathFuncs::DoIt(char *Buffer)
      {
      }
}

---------Module1.vb------------
Imports MathFuncs2dll.MyMathFuncs

Module Module1

    Sub Main()
        Dim mf As New MathFuncs2dll.MyMathFuncs
        Dim a As Double
        Dim b As Double
        Dim intarray(1000) As Integer

        a = 7.4
        b = 99

        Console.WriteLine("a + b = " + mf.Add2(a, b).ToString)
        mf.doit(intarray)
        Console.Write("Press <enter> to exit program")
        Console.ReadLine()

    End Sub

End Module
--------------------------------------

Thanks for any help received.
0
Comment
Question by:apmtva
  • 5
  • 4
  • 2
11 Comments
 
LVL 86

Assisted Solution

by:jkr
jkr earned 50 total points
ID: 18046349
>>but I can't make arrays or pointers work.

Check out http://support.microsoft.com/kb/205277 ("How to pass arrays and strings between Visual Basic and C functions or between Visual Basic and C++ functions by using Visual Basic 6.0") which describes the concepts behind that and explains how to do it.
0
 

Author Comment

by:apmtva
ID: 18047577
Before I go through this excersize I noticed that it said it was for VB6. I am using VS2006 .NET. Will the examples compile and work under VS2005?
0
 

Author Comment

by:apmtva
ID: 18047593
Sorry, I fat fingered the response above. I meant VS2005 not VS2006.
0
 
LVL 86

Expert Comment

by:jkr
ID: 18048144
Yes, that will still work. It's just that these issues arose earlier alread ;o)
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 18048436
Dim intarray(1000) As Integer
mf.doit(intarray)

C++/CLI prototype of doit function:

void doit(array<int>^ intarray);

If you have problem with some C++/CLI function prototype, show desired prototype in VB and I will help you to translate this to C++/CLI.
BTW, for functions shown in your sample, it is better to declare them as static, because they don't use any class members. For VB client, these fuctions will be Shared and can be used as .NET Math class functions.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:apmtva
ID: 18048980
AlexFM

Thank yuou very much. What I needed was the ability in the C++ dll to set an array of values that vb could then use. The second part of my problem is that I need to sned a string to the c++ dll and have the c++ dll send a strng back to vb. I think I could do this with the array<char> but I am not sure how to deal with it inside of c++. I need to copy the array of charas to a simple char mString[1000] data type. How would I do this or is there a better way to deal with strings in a vb c++ inteface.

Again thanks for the array. It worked greate.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 18051679
Well, write functions that you need in VB .NET (prototypes and simplefied code) and post here, I will show you how to do this in C++/CLI. For example, you want such function:

public function GetName() as string
    return "Test"
end function

In C++/CLI this is:

public: String^ GetName()
{
    return L"Test";
}

So, instead of description, give me VB code, this is better.
0
 

Author Comment

by:apmtva
ID: 18053777
VB Code
------------------------------------------------------------------
dim strWork1 as sSring
dim strWork2 as String
dim bArray[1000] as Byte

strWork2 = "10.10.10.10"
Call SetTCPIPAddress(strWork2)

strWork1 = GetVersion()
GetBuffer(bArray)
PutBuffer(bArray)-
-----------------------------------------------------------------

C++ Code
------------------------------------------------------------------

void MyMathFuncs::StrTCPIPAddress(String^ Address)
{
  char TCPIPAddress[63];
  ???? Copy the string Address to TCPIPAddress to be used later
}
String^ MyMathFuncs::GetVersion()
{
  // Call to void Get_Version(Char *Buffer, int BufLen)

  char strWork1[1000];
  EGD_Version(strWork1, 1000);

  ???? Return strWork1
}

void MyMathFuncs::GetBuffer(array<char>^ bytearray)
{
  char buffer[1000];

  // Internal work to populate buffer

  ???? Copy buffer into bytearray
}

void MyMathFuncs::PutBuffer(array<char>^ bytearray)
{
  char buffer[1000];

  ???? Copy bytearray into buffer
}
------------------------------------------------------------------
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 18054177
void MyMathFuncs::StrTCPIPAddress(String^ Address)
{
  char TCPIPAddress[63];
  IntPtr p = Marshal::StringToHGlobalAnsii(Address);
  strcpy(TCPIPAddress, p.ToPointer());
  Marshal.FreeHGlobal(p);
}

String^ MyMathFuncs::GetVersion()
{
  // Call to void Get_Version(Char *Buffer, int BufLen)

  char strWork1[1000];
  EGD_Version(strWork1, 1000);

  return Marshal::PtrToStringAnsi(IntPtr((void*)strWork1));
}

void MyMathFuncs::GetBuffer(array<char>^ bytearray)

What is VB type that you need? .NET Char type is Unicode character - 2 bytes. C++ char byte is 1 byte. .NET type which matches to C++ char is Byte. Assuming that VB client exprcts Byte:

void MyMathFuncs::GetBuffer(array<unsigned char>^ bytearray)
{
    unsigned char buffer[1000];

    Marshal::Copy(bytearray, 0, IntPtr((void*)buffer, bytearray.Length);
}

void MyMathFuncs::PutBuffer(array<char>^ bytearray)
{
  char buffer[1000];

   Marshal::Copy(IntPtr((void*)buffer), bytearray, 0, n);  // n is array length - your program should know this
}

About last function, it is better to rewrite it by this way:

array<char>^ MyMathFuncs::GetArray()
{
  char buffer[1000];
  ...

  array<char>^ bytearray = gcnew array<char>(n);  // n is required length, <= 1000

   Marshal::Copy(IntPtr((void*)buffer), bytearray, 0, n);  

   return bytearray;
}
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 450 total points
ID: 18054199
Correction: in last three functions, I mean unsigned char instead of char. You can use char as well, this requires some casting.
0
 

Author Comment

by:apmtva
ID: 18057306
Thanks for all the help. I am now able to write the DLL function in C++ to wrap the LIB that I need. However I am having an additonal problem when I referenece the routines in the LIB. I posted this as a separate problem if you want to have a look.

Thanks again.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

910 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now