marshalling c style command line arguments

K

Kelvin Johnson

I am wrapping a legacy C api using C++\CLI. I will use the resulting classes
from C# and VB.net. I need to pass command line arguments from the .net
languages to the c api functions, so I've created a custom marshaller for the
task. The problem is that I get an error stating that a conversion from
type1 to type2 is not supported. I've read the MSDN documentation (along
with an apress title or two), but I am still missing somthing.

Here is my code
VS.NET 2008:

The custom marshaler:
#pragma once

#include <msclr/marshal.h>

namespace msclr {
namespace interop {
template<>
ref class context_node<unsigned char **, System::String ^>
: public context_node_base
{
private:
unsigned char **toPtr;
int from_count;

public:
context_node(unsigned char **& toObject, array<System::String^>^
fromObject)
{
// (Step 4) Initialize toPtr to the appropriate empty value.
from_count = fromObject->GetLength(0);

// (Step 5) Insert conversion logic here.
toPtr =(unsigned char**) new unsigned char[from_count];
for(int i=0;i<from_count;i++)
{
cli::array<unsigned char>^ char_array =
System::Text::Encoding::ASCII->GetBytes(fromObject);
cli::pin_ptr<unsigned char> char_pin_ptr = &char_array[0];
unsigned char* char_star = new unsigned char[char_array->GetLength(0)];
toPtr = char_star;
}

// (Step 6) Set toObject to the converted parameter.
toObject = toPtr;
}
~context_node()
{
this->!context_node();
}
protected:
!context_node()
{
// (Step 7) Clean up native resources.
for(int i=0;i<from_count;i++)
{
delete [] toPtr;
}
delete [] toPtr;
}
};
}
}

The wrapper class:

public ref class Session
{
public:
//array<System::String^ >^ args = string[] args
Session(array<System::String^ >^ args)
{
Console::WriteLine(args[1]);
marshal_context context;// = gcnew marshal_context();
unsigned char **argv;
argv = context.marshal_as<unsigned char**>(args);
//STATUS error = NotesInitExtended (args, argv);

//if (error)
//{
// fprintf (stderr, "\nError initializing Notes.\n");
// throw std::exception("Error initializing Notes");
// //return (1);
//}
}

~Session()
{
NotesTerm();
}
};
 
K

Kelvin Johnson

Hello Giovanni,

Thank you very much for your reply. This should be just what I need to
better understand custom marshalers in this context.

I am stuck with using char ** since this is what the 3rd party api is
expecting. I will have to convert the strings from Unicode to ANSI.

I will try this out tonight.

Thanks again.

Kelvin
 
G

Giovanni Dicanio

Thank you very much for your reply.

You're welcome.
I am stuck with using char ** since this is what the 3rd party api is
expecting. I will have to convert the strings from Unicode to ANSI.

I will try this out tonight.

OK, if you have any problem let us know.

Note that sometimes when the char ** are involved, the end of the string
pointer array is marked with a NULL pointer; in the code I posted, I did not
do that, but the marshaling class has a Count() method to get the number of
strings in the array.
However, it is trivial to modify the code in case you want a NULL pointer
termination for the array.

Giovanni
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top