Il punto è che il modello di stringa .NET non c'entra niente con quello del C; in .NET una stringa è una sequenza immutabile di caratteri Unicode, per cui non puoi passarla come se nulla fosse ad una funzione C che si aspetta un qualche genere di buffer di char. Per questo motivo, il marshaling delle stringhe da mondo managed a mondo unmanaged non è semplicissimo; leggi qui e qui.

In ogni caso, di base la cosa più semplice se la stringa viene modificata è passare uno by value uno StringBuilder (dimensionato opportunamente), impostando il flag Ansi alla Declare.
Se invece la stringa non viene modificata basta una semplice String passata by value (sempre marcando la Declare come Ansi).

Per inciso, la cosa migliore sarebbe che la funzione C lavorasse direttamente in Unicode (wchar_t *), in modo da evitare la perdita di informazioni che si ha nel convertire in Ansi.