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
458 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
returning a dereferenced pts in C++ 10 171
VS2015 compilation and missing DLLs 9 190
Copy output image from TWindowsMediaPlayer 6 66
designing in object programming 12 129
Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
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…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

738 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