all'interno della dll, posso fare quello che "voglio
Si. Il problema riguarda solo il passaggio di parametri.
Entrando nel dettaglio, il fatto che ti funzioni "ora" non significa che funzioni "sempre".
L'implementazione di una std::basic_string<> (ci cui una string è solo un typedef) varia da debug mode a release mode e non solo per il codice del debug appunto, ma anche per gli allocatori usati. Non c'è nessuna garanzia che la malloc o operator new o altro allocatore siano gli stessi tra il codice sorgente e la DLL, quindi non puoi fare nessuna assunzione che qualcosa allocato da una parte sia deallocabile dall'altra.
E' comunque sufficiente provvedere a fornire due funzioni per risolvere il problema.
codice:
void* DLLAlloc(unsigned int);
void DLLFree(void*);
Il principio è semplice: se allochi con DLLAlloc() liberi la memoria con DLLFree().
Per quanto riguarda la tua struttura la cosa si ripete. Però devi decidere dove e come allocare i campi. Se l'allocazione avviene lato sorgente, sei a posto; se avviene lato DLL sei a posto; se mischi le cose, sei del gatto.
E comunque la struttura è meglio passarla come puntatore.
codice:
extern "C" struct comando{
	char * cmd;
	char * p1;
	char * p2;
	char * pNum;
	char * pAgg;
	};

extern "C" _declspec(dllexport) void foo(comando* cmd)
{
std::string convert = cmd->cmd;
//etc
Sleep(200); 
//blabla
}