Função xHarbour com C

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Função xHarbour com C

Mensagem por MARCELOG »

Olá pessoal,
antes de mais nada, quero dizer que esse tópico "travestido" está na seção de "outras linguagens de programação".

Apesar de email enviado ao moderador quanto à remoção para aquela seção não obtive resposta.

Então, novamente, estou postando na linguagem que eu acho certa, ou seja, xHarbour, em face da possibilidade de integração com o C.

Veja que a função inicia-se com HB_FUNC...

Mas é o seguinte.

O recurso pretendido abaixo não está na biblioteca pgsql da contrib, e acho que até pode ser integrada a mesma e ajudar a todos.

Refere-se a possibilidade de verificar as notificações retornadas do servidor PostgreSql para a seção/ terminal ouvinte.

Ela até já está retornando valores (3 caracteres), porém os mesmos estão inteligíveis.

Na verdade, somente preciso do valor de relname que, no prototipo da função é um ponteiro (pelo que li e entendi a respeito).

Desde já obrigado.

MarceloG

Código: Selecionar todos

HB_FUNC (PQNOTIFIES)

typedef struct pgNotify {
char *relname; /* nome da condição de notificação */
int be_pid; /* ID de processo do processo servidor */
char *extra; /* parâmetro de notificação */
} PGnotify;

{
PGnotify *notify;
notify = PQnotifies(( PGconn * ) hb_parptr(1));
[color=#FF0000]hb_retc( notify->relname); // deveria retonar o nome da notificação [/color]
PQfreemem(notify);
}
Água mole em pedra dura tanto bate que até espirra!
rodrmigu
Usuário Nível 3
Usuário Nível 3
Mensagens: 150
Registrado em: 27 Nov 2007 15:13
Localização: Indaiatuba SP

Re: FUNÇÃO XHARBOUR COM C

Mensagem por rodrmigu »

Marcelo,

Nao testei, mas seria mais ou menos isso:

Código: Selecionar todos

HB_FUNC (PQNOTIFIES)
{
   PGnotify *notify = hb_xgrab( sizeof(notify *) );
   notify = PQnotifies(( PGconn * ) hb_parptr(1));
   hb_retc(notify->relname);
   hb_xfree(notify);
}
[]'s
Rodrigo
MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Re: FUNÇÃO XHARBOUR COM C

Mensagem por MARCELOG »

Olá Rodrigo,
muito obrigado pela atenção.
Entretanto, da forma apresentada, a função não compila e apresenta erro.
No caso específico, o que hb_xgrab faz?

MarceloG
Água mole em pedra dura tanto bate que até espirra!
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Re: FUNÇÃO XHARBOUR COM C

Mensagem por Maligno »

o que hb_xgrab faz?
Essa função é equivalente à _xgrab() do Clipper, que aloca uma porção de memória.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
rodrmigu
Usuário Nível 3
Usuário Nível 3
Mensagens: 150
Registrado em: 27 Nov 2007 15:13
Localização: Indaiatuba SP

Re: FUNÇÃO XHARBOUR COM C

Mensagem por rodrmigu »

Marcelo,

Fiz uma pequena mudança.

Código: Selecionar todos

HB_FUNC (PQNOTIFIES)
{
   PGnotify *notify; 
   notify = PQnotifies(( PGconn * ) hb_parptr(1));
   hb_retc(notify->relname);
   PQfreemem(notify);
}
Coloque dentro do seu postgres.c e tente compilar novamente.

[]'s
Rodrigo
MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Re: FUNÇÃO XHARBOUR COM C

Mensagem por MARCELOG »

Olá Rodrigo,
obrigado de novo por responder.
Mas conforme início do tópico, eu já tentei assim e dá erro.
Se você fizer referência com & funciona, mas o resultado é o mesmo (3 caracteres).
Acho, e somente acho, que o problema é o seguinte:

A estrutura PGnotify contém três elementos, sendo dois deles ponteiros.

typedef struct pgNotify {
char *relname; /* ponteiro - nome da condição de notificação */
int be_pid; /* ID de processo do processo servidor */
char *extra; /* ponteiro - parâmetro de notificação */
} PGnotify;

Em c, para se acessar o elemento nessas estruturas você usa:
estrutura.elemento ou, conforme o caso, (estrutura.)elemento.

Nesse caso, é melhor usar estrutura->elemento, que sempre vai ser traduzido como (estrutura.)elemento sem haver confusão de precedência de operador (foi o que entendi).

O problema é que notify.relname ou notify->relname não retornam o "valor" do ponteiro.

E se você mandar retornar apenas notify como caracter "hb_retc(notify)", o efeito é o mesmo.

Sempre retornam 3 caracteres.

Acho que hb_retc está retornando toda a estrutura de 3 elementos e não só o primeiro elemento da mesma, que é do tipo ponteiro para char.

Alguma sugestão.

MarceloG
Água mole em pedra dura tanto bate que até espirra!
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Re: FUNÇÃO XHARBOUR COM C

Mensagem por Maligno »

MARCELOG escreveu:Mas conforme início do tópico, eu já tentei assim e dá erro.
Se você fizer referência com & funciona, mas o resultado é o mesmo (3 caracteres).
Esses 3 caracteres que você viu representam o ponteiro em si, não a string. Isso porque o operador & representa "O endereço de", ao passo que o operador * representa "NO endereço de".

Não vejo erro algum neste último código do Rodrigo. O anterior, onde tinha a chamada à hb_xgrab() tinha realmente erro de lógica, já que a função PQnotifies() já retorna um ponteiro. Não há necessidade de alocar espaço que já é alocado por PQnotifies(). Aliás, daí a utilidade de PQfree(), que vai liberar essa memória.

Nesse último código a linha hb_retc(notify->relname), a meu ver, está correta, pois relname é um ponteiro para char e é isso o que hb_retc() espera.
Em c, para se acessar o elemento nessas estruturas você usa:
Usa estrutura.elemento para acessar o elemento diretamente ou...
Nesse caso, é melhor usar estrutura->elemento, que sempre vai ser traduzido como (estrutura.)elemento sem haver confusão de precedência de operador (foi o que entendi).
... estrutura->elemento para acessá-lo pelo ponteiro da estrutura (acesso por referência indireta). Nesse caso, você pode também fazer um derreferenciamento da estrutura: (*estrutura).elemento, o que dá no mesmo (não é usual). Essa forma que comentou, (estrutura.)elemento, não existe. Só pode dar erro de compilação.
E se você mandar retornar apenas notify como caracter "hb_retc(notify)", o efeito é o mesmo.
Sempre retornam 3 caracteres.
Sim, esse 3 caracteres são o ponteiro de relname e não o valor referenciado pelo ponteiro.

Como eu disse, o último código apresentado pelo Rodrigo deveria funcionar perfeitamente. Não tenho a menor idéia do que pode estar errado.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Re: FUNÇÃO XHARBOUR COM C

Mensagem por MARCELOG »

É Rodrigo,
desse jeito também não funciona, o programa gera um erro sem qualquer informação e aborta.

Código: Selecionar todos

HB_FUNC (PQNOTIFIES)
{
   PGnotify *notify; 
   notify = PQnotifies(( PGconn * ) hb_parptr(1));
   hb_retc(notify->relname);
   PQfreemem(notify);
}
Aí, lendo na internet, efetuei as seguintes modificações:

Código: Selecionar todos

HB_FUNC (PQNOTIFIES)
{
   PGnotify *notify = (PGnotify *) malloc(sizeof(PGnotify));
   notify->relname = (char *) malloc(sizeof(char)); 
   PQconsumeInput (( PGconn * ) hb_parptr(1));
   notify = PQnotifies(( PGconn * ) hb_parptr(1));
   hb_retc(notify->relname);
   PQfreemem(notify);
}
Agora, houve alteração no retorno, sendo que, quando usada, a primeira referência a notify->relname é verificada, mas não compila na segunda ocorrência.

Tá empacado.

MarceloG


---
Nota da Moderação (Maligno):
A presente mensagem foi editara para a inserção das tagas que facilitam a visualização de código. Por favor, não se esqueça delas.
Água mole em pedra dura tanto bate que até espirra!
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Re: FUNÇÃO XHARBOUR COM C

Mensagem por Maligno »

A alocação de memória desse segundo código, conforme eu havia comentado, não deve ser necessário, já que há uma exigência do uso de PQfreemem(), o que leva a crer que a memória é alocada pela função chamadora. Como ela devolve um ponteiro, você só precisa liberar a memória, e não alocar.
Além do que, se for o caso de usar malloc(), você precisa liberar a memória alocada, usando free(<pointer>).
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
rodrmigu
Usuário Nível 3
Usuário Nível 3
Mensagens: 150
Registrado em: 27 Nov 2007 15:13
Localização: Indaiatuba SP

Re: FUNÇÃO XHARBOUR COM C

Mensagem por rodrmigu »

Olá,

O uso do malloc não faz sentido pq já é retornado um ponteiro (alocado) e daí vc usa o retorno e libera a memória. Veja a documentação.

O que faltava era o PQConsumeInput apenas. Use a rotina como eu escrevi, sem o pqconsumeinput e pqisbusy e use-as por fora. Eu uso assim para um outro recurso, como o de mandar uma query e nao ficar esperando o resultado, mas busca-la quando estiver pronta no banco:

Código: Selecionar todos

do while ! lCancel .and. ! lQuery
   Sleep(300)
   UpdateCancelDialog()

   if PQconsumeInput(conn)
      if ! PQisBusy(conn)
         lQuery := .t.
      endif
   endif

   do while Gtk_events_pending()
      gtk_main_iteration()
   enddo
enddo

if ! lCancel
   res := PQgetResult(conn)
endif

do while (x := PQgetResult(conn) != NIL)
   PQclear(x)
enddo
[]'s
Rodrigo
MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Re: FUNÇÃO XHARBOUR COM C

Mensagem por MARCELOG »

Obrigado de novo!

Mas veja bem Rodrigo, a estrutura faz referência a um ponteiro tipo char de nome relname (char *relname).
Então estrutura.membro ou (*estrutura).membro ou estrutura->membro não vai acessar o valor de relname, que é um ponteiro para um char retornado de PQnotifies.
Não seria algo do tipo *(notify->relname).

MarceloG
Água mole em pedra dura tanto bate que até espirra!
rodrmigu
Usuário Nível 3
Usuário Nível 3
Mensagens: 150
Registrado em: 27 Nov 2007 15:13
Localização: Indaiatuba SP

Re: FUNÇÃO XHARBOUR COM C

Mensagem por rodrmigu »

Marcelo,

Está correto o que eu lhe passei. Pois a referência para um ponteiro de uma estrutura é essa mesmo notify->relname. Qualquer coisa, de uma olhada nos exemplos abaixo:

http://www.postgresql.org/docs/8.2/inte ... ample.html

[]'s
Rodrigo
MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Re: Função xHarbour com C

Mensagem por MARCELOG »

Olá pessoal,
tentativa e erro, demoraaaaaaaaaaaaaaaaaaaaaa!
Mas prá funcionar corretamente é necessário o seguinte:

Código: Selecionar todos

HB_FUNC (PQNOTIFIES)
{
   PGnotify *notify;
   PQconsumeInput (( PGconn * ) hb_parptr(1));
   while ((notify = PQnotifies(( PGconn * ) hb_parptr(1))) != NULL)
{
   hb_retclen(notify->relname,strlen(notify->relname)+1);
   PQfreemem(notify);
}
}
MarceloG

Ps: a situação acima, embora verifique (leia) todas as notificações pendentes em virtude do 'while', retorna apenas a última. Alguém pode dar uma ajuda para ela incluir essas notificações numa array e retornar a mesma.
Água mole em pedra dura tanto bate que até espirra!
Responder