2009-09-20 4 views
2

У меня есть dll, написанная на C++. И я p/вызываю, чтобы вызвать функции.эквивалент char * in C#

У меня есть это объявление C++.

int dll_registerAccount(char* username, char* password); 

Я сделал это заявление: DllImport

[DllImport("pjsipDlld")] 
static extern int dll_registerAccount(IntPtr username, IntPtr password); 

ли мой DllImport быть эквивалентом C++ с использованием IntPtr?

Большое спасибо за любые советы,

+1

Поскольку вы используете Sipek SDK от http://sites.google.com/site/sipekvoip/sipeksdk, могу ли я спросить, почему вы делаете свой собственный 'DllImport' когда SDK уже предоставляет вам обертки? –

ответ

20

C# способ сделать это, позволяя упаковщик обрабатывать char* вещи в то время как вы работаете со строкой:

[DllImport("pjsipDlld")] 
static extern int dll_registerAccount(
    [MarshalAs(UnmanagedType.LPStr)]string username, 
    [MarshalAs(UnmanagedType.LPStr)]string password); 

LPStr Заменить с LPWStr, если вы работаете с широкими гольцов.

0

Я побежал свою линию C++ через P/Invoke assistant:

public partial class NativeMethods { 

    /// Return Type: int 
    ///username: char* 
    ///password: char* 
    [System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="dll_registerAccount")] 
public static extern int dll_registerAccount(System.IntPtr username, System.IntPtr password) ; 

} 

Таким образом, вы были правы, он должен работать. Но есть некоторые автоматизированные маршалингом доступны, вы должны быть в состоянии сделать только:

[DllImport("pjsipDlld")] 
static extern int dll_registerAccount(string username, string password); 

Смотрите эту MSDN page о умолчанию маршалинге и перегружая его.

+2

Отличный пример того, почему вы не должны использовать помощник P/Invoke. –

+0

Стивен, вы, вероятно, правы, хотя в прошлом у меня был некоторый успех. –

+0

Это не сработает, потому что строки C# хранятся в виде широких массивов символов и то, что его метод ожидает, это однобайтовые массивы символов. Вы должны уточнить маршалера. – Blindy

1
[DllImport("pjsipDlld", CharSet = CharSet.Ansi)] 
    static extern int dll_registerAccount(string username, string password); 
2

StringBuilder для char *, так как длина неизвестна?

[DllImport("pjsipDlld")] 
static extern int dll_registerAccount(StringBuilder username, StringBuilder password); 
+1

Длина может быть неизвестна, но то, что входит и что происходит, - это постоянные строки (взятые отдельно, конечно, они не должны быть одинаковыми), поэтому они отлично отображают объект 'string'. – Blindy

+0

Да, я читал эти атрибуты (LPStr & LPWStr) после просмотра вашего ответа. Теперь имеет смысл. – ParmesanCodice

+0

Это закончилось тем, что отлично работает для меня, когда вы вызываете подпрограмму Fortran из C#, в то время как принятый ответ - нет. У меня тоже была известная длина, и это была версия, которая сработала. YMMV. –

0

Зная об условных соглашениях, это сработало. В моем случае мне нужно вызвать C++ DLL, но с экспортом C-стиля, который использует соглашение о вызове cdecl. Если у вас есть роскошь наличия исходного решения Visual Studio, перейдите в «Свойства -> C/C++ -> Дополнительно» и найдите его в разделе «Calling Convention». Это исправить это для меня:

[DllImport(DllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] 
// bool MyFunction(char* fileName) <-- From the DLL 
static extern bool MyFunction(string fileName);