2

First off, I'm a C# programmer, so my working knowledge of C++ is fairly limited. I took it back in college, but haven't touched it in 10 years, so please forgive me if this is relatively simple stuff.

I'm attempting to make a DLL that I can use in C# that implements the libwpd library.

I've managed to create a DLL that exports 2 functions that I can access via P/Invoke. The first returns a constant integer (generated by visual studio as a sample), the 2nd a string.

If I return a constant string from the function, it passes successfully to C# and I can read it on the other end, so I know the data is being passed back.

The problem I'm running into is with libwpd. I've had to modify their TextDocumentGenerator.cpp file to add the information to a char* instead of using the printf that they use so I can access it later.

I've added a variable definition to the public section of the header file so I can read it from the calling code.

Now, I'm trying to write a function that allows me to add the char* given by libwpd to the external char*.

I've come up with this:

char* addString(const char* addThis, char* toThis)
{
char* copier  = (char*)malloc(strlen(toThis) + 1 + 1);
strcpy(copier, toThis);
strcpy(copier, "1");

toThis = (char*)malloc(strlen(copier) + 1);
strcpy(toThis, copier);

return copier;
} 

But when I pass the information back, I get a blank string.

I call the function by calling totalFile = addString("\n", totalFile);

(I realize it should only technically add "1" to the string repeatedly, but it's not doing even that)

If i change the strcpy to strcat for the copier lines, it locks up.

I don't know how to create a program in C++ so I can even step through the functions to see what's happening.

Any assistance would be appreciated.

Trevor Watson
  • 415
  • 1
  • 8
  • 20
  • `strcpy(copier, toThis); strcpy(copier, "1");` - for one thing, the second `strcpy` overwrites the results of the first. – Steve Jessop Dec 13 '11 at 19:07
  • If you find yourself using `malloc` in C++, it almost always means you're doing something wrong. If you find yourself using `new` in C++, it may still mean you're doing something wrong; many of the common scenarios where `new` would be needed are already provided in the standard template library. – Brian Dec 13 '11 at 19:10
  • @Trevor A friendly tip: I would suggest compiling your C++ project as C++/CLI, and in the project create a managed wrapper for the native code. That way, it is MUCH cleaner interfacing with it. You just add a reference as usual and you can create managed instances of your wrapper, which contains unmanaged pointers to the native classes. – Max Dec 13 '11 at 19:21
  • Don't forget to write and export another function in your DLL to free the allocated string. DLL has it's own memory manager. – Gene Bushuyev Dec 13 '11 at 19:21

4 Answers4

6

Are you aware of existence of std::string? It's a class that handles strings in C++; char * is legacy from C.

std::string provides + operator, that does what you want.

Griwes
  • 8,805
  • 2
  • 43
  • 70
  • I wasn't aware of std::string. The existing code I have to work with and my school used char*, so that's what I was trying to use. I don't seem to have access to std::string (missing an include?) but will look for it. – Trevor Watson Dec 13 '11 at 18:47
  • He wants to call this from c#, so `std::string` is not going to work (at least for the parameters and return value). – crashmstr Dec 13 '11 at 18:53
  • #include . Next time, google for "cppreference " to get such information ;) – Griwes Dec 13 '11 at 18:53
  • 2
    @crashmstr, do you know that there are two ways of getting `char *` from string? `c_str()` and `&str[0]`? – Griwes Dec 13 '11 at 18:54
  • Blah. Apparently using #include conflicts with the existing required stream class from libwpd. C makes my eyes bleed. thanks for all your assistance. Not sure where I'm going from here. – Trevor Watson Dec 13 '11 at 18:58
  • After fiddling with it for a bit, std::string was the way to go and scrapping this monstrosity of a function. – Trevor Watson Dec 13 '11 at 19:33
3

You need to allocate enough space for the return string, copy the inital string into the destination buffer, and then call strcat to append the extra info.

For example:

char* addString(const char* addThis, const char* toThis)
{
    char* destination = (char*)malloc( strlen( addThis ) + strlen( toThis ) + 1 );
    strcpy( destination, toThis );
    strcat( destination, addThis );
    return destination;
} 

Don't forget you'll need to call free( destination ) at some point after calling this function.

EDIT: Of course, this is just me fixing the function proposed in your question. Really, it's not a great idea to return a pointer from a function and count on the caller to free it. Since you're using C++ rather than C, you'd likely be much better off using some C++ constructs, such as std::string or at the very least, wrapping the char* in a shared_ptr or similar.

If you're going to be writing C++, I'd recommend buying yourself a good book on the subject, it really is far too easy to shoot yourself in the foot if you don't know what you're doing.

Community
  • 1
  • 1
obmarg
  • 9,369
  • 36
  • 59
  • This is not necessarily a good idea. You've put the responsibility of the caller to free the block of memory you allocated. This is as bad as not using `shared_ptr`. You're allocating memory, then saying "be damned with it". Some may disagree, but I find this bad practice. – Moo-Juice Dec 13 '11 at 18:38
  • @Moo-Juice I agree, personally I'd never write a function like this. I was just fixing the mess of a function proposed in the question. Might edit in a disclaimer to that effect I suppose. – obmarg Dec 13 '11 at 18:39
  • The strcmp for the first one was what causing it to lock up when i changed it. Doing it as strcpy/strcmp let it run past this point. I'll probably look into sprintf or std::string if i can get past the linking errors. Thanks for the comments! – Trevor Watson Dec 13 '11 at 19:07
1

Since you are replacing a printf() call, sprintf() would probably be the easiest way to create your string.

sth
  • 222,467
  • 53
  • 283
  • 367
0

First off, Griwes is correct. You have no business doing what you are doing and marking this question as C++. The simple reason being, this is not how we work with strings in C++.

As you are a C# programmer you are well aware of the String class. Well, std::string is similar. It takes the leg-work out of dealing with strings so that you do not have to go down the painful route that you're going down.

To concatenate two strings together in C++, it's as simple as:

std::string a = "I slept with ";
std::string b = "a heavy heart.";
std::string c = a + b;

Voila.

Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • The downside to this is using legacy code or code written with char* originally. Can you convert from a std::string to a char* and back again without issue? I also don't have access to the std::string as it stands (missing an include somewhere). In school and in the existing source code that I'm modifying, char* was used so I used char*. I will definitely look into std::string though if I can get access to it. – Trevor Watson Dec 13 '11 at 18:46
  • 1
    @TrevorWatson, yes. in the above example, calling `c.c_str()` will give you a regular `const char*`. – Moo-Juice Dec 13 '11 at 18:55
  • @TrevorWatson: `std::string` is part of the standard template library. It will be included with any decent C++ compiler. Using `char *` instead of `std::string` is analogous to using `char[]` in C# instead of using a `System.String`. – Brian Dec 13 '11 at 19:04