Pergunta

Estou tendo problemas para fazer um back corda de algum código c eu escrevi.

Primeiro alguns geralmente unrealated informação de fundo: Eu gostaria de receber a string legível usuário para um TAPI TSP do API TAPI. Eu já implementou uma solução TAPI viável semi depender de correspondência nomes de driver de cordas armazenados, mas gostaria de mudar isso para trabalhar em permanant id linha é em vez disso, como um dos nossos clientes tem um (Alcatel) PBX que se recusa a trabalhar de outra maneira .

Em C, eu definir a função no meu arquivo de cabeçalho como:

__declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* DeviceName);

A função está escrito assim:

__declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* DeviceName)
{
    //tapi code here...

    //copy the string to DeviceName
    wcscpy(DeviceName, (wchar_t*)((char *)devCaps + devCaps->dwLineNameOffset));
}

Como dito acima, isso acabará por fazer algo útil, mas por enquanto eu vou ser feliz se abc é colocado na minha wchar_t * / StringBuilder e eu posso ver que em C #.

Em C # Eu definir a função como:

    [DllImport("SBW.Tapi.TapiInterop.dll", CharSet = CharSet.Auto)]
    static extern void GetDeviceName(long DeviceId, StringBuilder DeviceName);

Eu defino DeviceName como um StringBuilder porque uma string é immuatable e quero que o DeviceName a ser definido em C ( Este é recomendado por MS ). Eu também definir o tipo de retorno para void na tênue esperança de que isso também afeta alguma coisa (ver este artigo mono útil semi por um pseudo parcial explicação científica).

E chamá-lo assim:

StringBuilder name = new StringBuilder();
name.EnsureCapacity(100);
long n = 0;
GetDeviceName(n, name);

Eu atribuo meu depurador para o processo em execução, definir um ponto de interrupção, e aviso no código C que de alguma forma o StringBuilder é pervertida e é fornecido com o código não gerenciado como um ponteiro nulo.

Um AccessViolationException é posteriormente jogado em C #.

O que há de errado for?

removendo o parâmetro de comprimento ajuda. Eu sou capaz de adicionar "abc" para o meu parâmetro DeviceName em C. Eu quero essa variável longa no entanto! O que estou fazendo de errado ou perturbar de modo a forçar um acidente por ter tanto tempo parâmetro lá?

Foi útil?

Solução

em 32 bits de plataformas long é de 8 bytes (64 bits) de largura em NET e 4 bytes (32 bits) de largura em código nativo. Você precisa mudar o seu P / Invoke método como este:

[DllImport("SBW.Tapi.TapiInterop.dll", CharSet = CharSet.Auto)]
static extern void GetDeviceName(int DeviceId, StringBuilder DeviceName);

Desta forma, C # int e C long ter a mesma largura em 32 plataformas BITS.

Outras dicas

Eu quero que variável de longo porém

Em seguida, você deve definir o parâmetro em C como long long. Como Lucero apontou, uma longa no C ++ é de 32 bits, enquanto que uma longa em C # é 64 bits. Então, se você passar um valor de 64 bits onde a função C espera um valor de 32 bits, a função lê os extras 32 bits como o segundo parâmetro, o que obviamente resulta em um endereço errado para o buffer ...

O long c ++ é de 32 bits, o C # long é 64 bits, não é? Portanto, você precisa usar um int para o primeiro parâmetro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top