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
452 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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
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
 

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

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

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

Suggested Solutions

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

786 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