Pergunta

Eu tenho uma função C em uma biblioteca estática, vamos chamá-lo A, com a seguinte interface:

int A(unsigned int a, unsigned long long b, unsigned int *y, unsigned char *z);

Esta função irá alterar o valor de y um z (isto é, com certeza). Eu usá-lo de dentro de uma dinâmica biblioteca C ++, usando extern "C".

Agora, aqui é o que me stune:

  • y está ajustado corretamente, z não é alterado. O que exatamente querem dizer é que se ambos são inicializados com um valor (pontas) de 666, o valor apontado por y terá mudado após a chamada, mas não o valor apontado por z (ainda 666).
  • quando chamado de um binário C, esta função funciona perfeitamente (valor pontas por z é modificado).
  • se eu criar uma biblioteca fictícia C com uma função que tem o mesmo protótipo, e eu usá-lo de dentro do meu dinâmica C biblioteca ++, ele funciona muito bem. Se eu voltar a usar as mesmas variáveis ??para chamar A (..), eu obter o mesmo resultado como antes, z não é alterado.

Eu acho que os pontos acima mostram que não é um erro estúpido com a declaração dos meus variáveis.

Estou claramente preso, e eu não posso mudar a biblioteca C. Você tem qualquer pista sobre o que pode ser o problema? Eu estava pensando sobre um problema na interface do C / C ++, por exemplo, a forma como um char * é interpretado.

Edit: eu finalmente descobri o que era o problema. Veja abaixo a minha resposta.

Foi útil?

Solução 9

Primeiro de tudo, eu sou muito grato a todos por sua ajuda. Graças às numerosas ideias e pistas que você me deu, eu tenho sido capaz de finalmente resolver este problema. Seus conselhos ajudaram-me a pergunta que eu tinha como certo.

A resposta mais curta para o meu problema: O problema era que minha biblioteca C ++ usado uma versão antiga da biblioteca C. Esta versão antiga perdeu o quarto argumento. Como consequência, o quarto argumento foi, obviamente, nunca mudou.

Eu sou um pouco de vergonha agora que eu percebi que era o problema. No entanto, eu estava misslead pelo fato de que meu código estava compilando bem. Isso se deveu ao fato de que a biblioteca C ++ compilado contra a versão correta do lib C, mas em tempo de execução que usou a versão antiga estaticamente ligado com outra biblioteca que eu estava usando.

C++ Lib (M) ---> dyn C++ lib (N) ---> C lib (P) v.1.0
     |
     ------> C lib (P) v.1.1

(N) é uma biblioteca dinâmica que é ligado estaticamente com (P), versão 1.0. O compilador aceitou o chamado de (M) para a função com 4 argumentos, porque eu ligado contra (P) versão 1.1, mas em tempo de execução que usou a versão antiga do (P).

Sinta-se livre para editar esta resposta ou a pergunta ou pedir-me para fazê-lo.

Outras dicas

Parece que a diferença entre o a maneira sua biblioteca C e compilador C ++ é lidar com longos anseia . Meu palpite é que ele é que a biblioteca C é provavelmente pré padrão C89 e realmente tratar o 64bit long long como um 32bit longa. Sua biblioteca C ++ é manuseá-lo corretamente e colocando 64bits na pilha de chamadas e, portanto, corrompendo y e z. Talvez tente chamar a função através * int A (unsigned int a, sem sinal longa b, int não assinado * y, unsigned char z) , e ver o que você recebe.

Apenas um pensamento.

Esta é uma daquelas questões em que não há nada de errado, obviamente desde que você descreveu, mas as coisas não estão funcionando da maneira esperada.

Eu acho que você deveria Editar o seu post para dar muito mais informações a fim de obter algumas respostas sensatas. Em particular, vamos começar com: -

  • Que plataforma é este código para: Windows, Linux, algo embutido ou ...?
  • O compilador é o C biblioteca estática construída com?
  • O que compilador é o C ++ biblioteca dinâmica construído com?
  • O compilador é o C que pode chamar com êxito o biblioteca construída com?
  • Você tem um fonte de nível depurador? Se assim for, pode você pisa em o código C do C ++.

A menos que você está errado sobre A sempre modificar os dados apontado pelo Z, a única causa provável do problema é uma incompatibilidade entre o parâmetro passando convenções. O "long long" problema pode ser um indício de que as coisas não são como parecem.

Como último recurso, você pode comparar o desmontados C ++ código de chamada (que você diz falhar) eo código de chamada C (que você diz sucede), ou passo através das instruções da CPU com o depurador (sim, realmente - você' vai aprender uma boa habilidade, bem como resolver o problema)

Tanto quanto eu sei, longa, longa não faz parte do padrão C ++, talvez essa é a origem do problema.

Não sei. Tente debug-passo em um e ver o que acontece (alerta código de montagem!)

Talvez você pode quebrar a função original em uma biblioteca C que você chama de sua biblioteca C ++?

Com base em seus pontos 2 e 3, parece que isso poderia funcionar.

Se isso não acontecer, dá-lhe um outro ponto de depuração para encontrar mais pistas - ver quais dos seus bibliotecas do fracasso primeiro aparece em e verifique por 2 e 3 trabalho, mas isso não faz - o que é o mínimo diferença?

Você também pode tentar examinar a pilha que está configurado por seu chamada de função em cada caso, para verificar se a diferença é aqui -. Considerando diferentes convenções de chamada

Passo 1:. Comparar a ponteiros y e z passados ??do lado do C ++ com aqueles recebidos pela função C

P.S. Eu não quero soar óbvio, mas apenas duplo controlo aqui. Acho que quando você diz que z é modificado muito bem quando chamado a partir de um binário C, você quer dizer que os dados em que z está apontando é modificado apenas multa. A ponteiros y, e se z são passados ??por valor, então você não pode mudar os ponteiros.

Outro palpite: Tem certeza de que você está ligando com a instância direito da função em sua biblioteca C? Será que existem várias dessas funções disponíveis nas bibliotecas? Em C o ligador não se preocupa com o tipo de retorno ou a lista de parâmetros para decidir como resolver uma função - apenas o nome é importante. Então, se você tem múltiplas funções com o mesmo nome ...

Você pode programaticamente verificar a identidade da função. Criar uma biblioteca C que chama sua função A com alguns parâmetros de teste e que funciona bem e que imprime o ponteiro para a função A. Ligação a biblioteca em seu aplicativo C ++. Em seguida, imprima o ponteiro para a função original A como visto a partir do código C ++ e comparar o ponteiro com o observado pela sua biblioteca C quando invocado no mesmo processo.

Mais uma vez, um exemplo óbvio, mas quem sabe ... Tem certeza a função C você está invocando é apátrida, ou seja, a sua saída depende apenas de suas entradas? Se a função não apátrida é, então pode ser que o estado "oculto" é responsável pelo comportamento diferente (não alterar os dados apontado pelo z) da função quando chamado a partir de seu aplicativo C ++.

Em seu programa C ++, é o protótipo declarado com extern "C"?

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