How to integrate class-libraries?

I am trying to write a PC Software in Visual Studio 2008 with c++ to control the Maestro 6-Channel Servo USB Cotroller. I’ve downloaded the Pololu USB Software Development Kit and want to integrate the class libraries into my application. I tried to integrate some dll-files but with no success. As far as I know, I need a header-file and a lib-file to do that, but I can’t find them in your Development Kit.

Regards,
Steven.

That would be true if the DLLs were Win32 DLLs, but they are actually .NET assemblies. They contain enough information inside them so that you don’t need a header or lib file. You can add them to a .NET project the same way that “System” and “System.Windows.Forms” are added to the project: In the Project menu, select Properties. Under “Framework and References”, click “Add New Reference…”. Go to the Browse tab. Select the DLL file you want to add.

To use the Maestro, you at least need to reference UsbWrapper.dll and Usc.dll (you might need to reference Bytecode.dll, and Sequencer.dll too because some of the functions in Usc.dll depend on them, but I’m not sure). UsbWrapper.dll comes precompiled with the Pololu USB SDK. You can compile the other DLLs yourself by opening up Usc\Usc.sln in Visual Studio C# Express Edition (or Visual Studio) and building the solution.

Alternatively, if you have a non-express version of Visual Studio, then you can add Usc.csproj, ByteCode.csproj, and Sequencer.csproj as projects in your solution and reference them as projects instead of DLLs. Then the needed DLLs will get automatically built when your build your solution.

Let me know how this works!

-David

I already tried this and had no success. I looked in the msdn Library and found a note:

I was using a MFC Application and changed now to CLR. I added some references to usc.dll and UsbWrapper.dll according to your instructions. After that I added the following code to my application:

#using <UsbWrapper.dll>
#using <usc.dll>

But I still have no access to the usc-class.

I’ve never seen a “using” statement like that before. After adding a reference to Usc.dll (as described in my first), try this:

using namespace Pololu::Usc;

Or just try using the fully qualified names, like this:

Pololu::Usc::Usc::getConnectedDevices();

-David

It works! Thank You!

Hello,

I’m using Visual Studio 2010 with C++ and the Micro Maestro.
I was wondering if there is another way to reference the DLLs?

When I tried doing this in my application, there is no browse tab.
I switched to the CLR, but this causes the rest of my code (using OpenCV) to not compile. After a few hours of reading up on it and changing the configuration I finally got my code to compile, but I get a warning from OpenCV saying that it will not be able to capture pictures from the camera, and sure enough, it doesn’t.

Which brings me back to my question- is there another way to reference the necessary files to be able to use the Micro Maestro without using CLR?
And I’m not sure if this makes a difference, but I am not using a GUI/form, I am only want to run the application from an executable.

Thanks for reading,
-Chris

I’m not sure how much of this you know already, but here’s the deal as I understand it:

There are two main types of EXE/DLL files in Windows:

  • Unmanaged, a.k.a. WIN32. These executables contain x86 instructions which are probably executed by your CPU directly.
  • Managed a.k.a. CLR/CIL/.NET. These executables contain .NET bytecode instructions which are executed by the .NET framework using a just-in-time compiler. These executables can use managed types from the .NET framework like System.Collections.Generic.List which benefit from garbage collection.

When you’re writing C++ code, you can compile it in to either type of executable. Managed executables can call functions in Unmanaged executables. As far as I know, it’s not possible for Unamanaged executables to call functions in Managed executables because the Unmanaged code can’t understand Managed types.

The Maestro DLLs are Managed so they have to be called by Managed code.

I think that the easiest thing for you is to change your project back to Unmanaged, and just use the virtual COM port to communicate with the Maestro.

Alternatively, perhaps you could extract all the OpenCV code in to an unmanaged DLL. Then your main application can be Managed, and call the OpenCV DLL and the Maestro DLL. I don’t know how hard that would be for you. The benefit of this is that you get to write Managed code.

You could also learn how to use the WinUSB API and SetupAPI and write your own Unmanaged code to talk to the Maestro. This is a pretty hard task though, because the SetupAPI is complex.

–David

Actually that was pretty useful, I looked more into it and and also into how my project is currently compiled, and I think that I can still use the Pololu managed DLL’s.

But I’m having a problem getting a basic project compiled without a user interface.
I’m trying to get the MaestroEasyExampleCPP’s function ‘TrySetTarget’ to work with my main I just wrote us real quick:

using namespace std;
#include <iostream>
#include "servos.h"

int main()
{
	for(int i=0; i< 10; i++)
	{
		int temp;
		cout << "Input 0 or 1";
		cin >> temp;
		if (temp ==0)
			TrySetTarget(0, 1000 * 4); 
		if (temp ==1)
			TrySetTarget(0, 2000 * 4);
	}
}

and the .h file

using namespace Pololu::Usc;

Usc^ connectToDevice()
{
	// Get a list of all connected devices of this type.
	List<DeviceListItem^>^ connectedDevices = Usc::getConnectedDevices();

	for each (DeviceListItem^ dli in connectedDevices)
	{
		// If you have multiple devices connected and want to select a particular
		// device by serial number, you could simply add a line like this:
		//   if (dli.serialNumber != "00012345"){ continue; }

		Usc^ device = gcnew Usc(dli); // Connect to the device.
		return device;             // Return the device.
	}
	throw gcnew Exception("Could not find device.  Make sure it is plugged in to USB " +
                "and check your Device Manager (Windows) or run lsusb (Linux).");
}


void displayException(Exception^ exception)
{
	StringBuilder^ stringBuilder = gcnew StringBuilder();
	do
	{
		stringBuilder->Append(exception->Message + "  ");
		if (exception->GetType() == Win32Exception::typeid)
		{
			stringBuilder->Append("Error code 0x" + ((Win32Exception^)exception)->NativeErrorCode.ToString("x") + ".  ");
		}
		exception = exception->InnerException;
	}
	while (exception != nullptr);
		MessageBox::Show(stringBuilder->ToString(), this->Text, MessageBoxButtons::OK, MessageBoxIcon::Error);
}


void TrySetTarget(Byte channel, UInt16 target)
{
	Usc^ device;
	try
	{
		device = connectToDevice();           // Find a device and connect.
		device->setTarget(channel, target);
	}
	catch (Exception^ exception)  // Handle exceptions by displaying them to the user.
	{
		displayException(exception);
	}
	finally  // Do this no matter what.
	{
		delete device;  // Close the connection so other processes can use the device.
	}
}

Any help? Or is there a good tutorial that you know of?

I think that the easiest way for you to make a C++ command-line app that uses the Maestro would be to start with MaestroEasyExample and then modify the “main” function found in MaestroEasyExample.cpp. Currently, that function has 3 lines of code to open up a new MainWindow and and display it. You could replace those lines of code with your own code.

You won’t be easily able to call TrySetTarget because it is defined in the MainWindow class but you can copy the functions you need to MaestroEasyExample.cpp.

If you have further trouble, please tell us exactly what error message or unexpected behavior you are getting.

–David