We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpIntegration › Processing and the libnfc library in C
Pages: 1 2 
Processing and the libnfc library in C (Read 7455 times)
Processing and the libnfc library in C
Jan 13th, 2010, 7:57am
 
Is there any way to make calls to the libnfc library (written in C) from within Processing

I've read some posts that talk about JNI and JNative as possibilities to achieve this, are they a real possibility Can someone give me some indication of where to start
Re: Processing and the libnfc library in C
Reply #1 - Jan 24th, 2010, 5:27pm
 
My report on the progress I've made so far:

My first step was to make part of the libNFC functionality available in Java, and after digging a little big I found about JNI and SWIG. Since SWIG seemed to take care of some of the hassle for me, my first try was using SWIG and Cygwin. Following the various SWIG tutorials available, I first created a simple test.c file as bellow:

Code:
#include "libnfc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static dev_info* pdi;

int connectRFID() {
  pdi = nfc_connect();
  if (pdi != INVALID_DEVICE_INFO) {
nfc_initiator_init(pdi);

// Drop the field for a while
nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);

// Let the reader only try once to find a tag
nfc_configure(pdi,DCO_INFINITE_SELECT,false);

// Configure the CRC and Parity settings
nfc_configure(pdi,DCO_HANDLE_CRC,true);
nfc_configure(pdi,DCO_HANDLE_PARITY,true);

// Enable field so more power consuming cards can power themselves up
nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);

return 1;
 } else return 0;
}


I then created the interface file test.i:

Code:
%module test
%{
  #include "libnfc.h"
  extern dev_info* pdi;
  extern int connectRFID();
%}

extern dev_info* pdi;
extern int connectRFID();


Finally in Cygwin I ran the follow instructions:

Code:
$ swig -java test.i
$ gcc -c test.c test_wrap.c -I/c/'Program Files'/Java/jdk1.6.0_18/include -I/c/'Program Files'/Java/jdk1.6.0_18/include/win32 -l/c/cygwin/usr/include
$ gcc -shared test.o test_wrap.o -mno-cygwin -Wl,--add-stdcall-alias -o test.dll


The last input resulted in the following inexplicable errors:

Code:
test.o:test.c:(.text+0x7): undefined reference to `_nfc_connect'
test.o:test.c:(.text+0x26): undefined reference to `_nfc_initiator_init'
test.o:test.c:(.text+0x43): undefined reference to `_nfc_configure'
test.o:test.c:(.text+0x60): undefined reference to `_nfc_configure'
test.o:test.c:(.text+0x7d): undefined reference to `_nfc_configure'
test.o:test.c:(.text+0x9a): undefined reference to `_nfc_configure'
test.o:test.c:(.text+0xb7): undefined reference to `_nfc_configure'
test.o:test.c:(.text+0xdf): undefined reference to `_nfc_disconnect'
test_wrap.o:test_wrap.c:(.text+0x91): undefined reference to `_pdi'
test_wrap.o:test_wrap.c:(.text+0xb3): undefined reference to `_pdi'
collect2: ld returned 1 exit status


Which refers to the libNFC functions I have in libraries in C:\cygwin\usr\include. Thinking I was missing something about SWIG and since the *.c file was quite simple, I gave it a shot with "pure" JNI.

Following a simple NetBeans tutorial I created the following Main.java:

Code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package libnfc;
/**
*
* @author Augusto
*/
public class Main {
   static {
 System.load("C:\\NetBeans\\LibNFC\\LibNFCNative\\dist\\LibNFCNative.dll");
   }
   public Main() {
   }
   /**
    * @param args the command line arguments
    */
   public static void main(String[] args) {
 // TODO code application logic here
  System.out.println(new Main().nativeTagID());
   }
   private native String nativeTagID();
}


I then generated the LibNFCNative.h file with:

Code:
C:\jdk1.6.0_18\bin\javah.exe -o LibNFCNative.h -jni -classpath C:\NetBeans\LibNFC\build\classes libNFC.Main 



My final piece of code was the LibNFC.c file:

Code:
#include <jni.h>
#include <stdio.h>
#include "LibNFCNative.h"
#include "libnfc.h"
#include <stdlib.h>
#include <string.h>

JNIEXPORT jstring JNICALL Java_libnfc_Main_nativeTagID(JNIEnv *env, jobject obj) {

   char buf[64];

   // Associate pdi with the RFID reader
   dev_info* pdi;
   pdi = nfc_connect();

   if (pdi != INVALID_DEVICE_INFO) {
   nfc_initiator_init(pdi);

   // Drop the field for a while
   nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);

   // Let the reader only try once to find a tag
   nfc_configure(pdi,DCO_INFINITE_SELECT,false);

   // Configure the CRC and Parity settings
   nfc_configure(pdi,DCO_HANDLE_CRC,true);
   nfc_configure(pdi,DCO_HANDLE_PARITY,true);

   // Enable field so more power consuming cards can power themselves up
   nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);

   buf[0] = "Success";
   } else buf[0] = "Failure";

   return (*env)->NewStringUTF(env, buf);
}


After adding "-mno-cygwin -Wl,--add-stdcall-alias -shared -m32" in the output for the Compiler, and adding the following folders:

Code:
C:/jdk1.6.0_18/include
C:/jdk1.6.0_18/include/win32
C:/Documents and Settings/Augusto/Desktop/libnfc-1.2.1-vs2005/src


Finishing with dist/LibNFCNative.dll in the Linker, I have the exactly same errors of when I tried it with SWIG:

Code:
gcc -mno-cygwin -Wl,--add-stdcall-alias -shared -m32    -mno-cygwin -shared -o dist/LibNFCNative.dll build/Debug/Cygwin-Windows/LibNFC.o  
build/Debug/Cygwin-Windows/LibNFC.o: In function `Java_libnfc_Main_nativeTagID':
/cygdrive/c/NetBeans/LibNFC/LibNFCNative/LibNFC.c:14: undefined reference to `_nfc_connect'
/cygdrive/c/NetBeans/LibNFC/LibNFCNative/LibNFC.c:17: undefined reference to `_nfc_initiator_init'
/cygdrive/c/NetBeans/LibNFC/LibNFCNative/LibNFC.c:20: undefined reference to `_nfc_configure'
/cygdrive/c/NetBeans/LibNFC/LibNFCNative/LibNFC.c:23: undefined reference to `_nfc_configure'
/cygdrive/c/NetBeans/LibNFC/LibNFCNative/LibNFC.c:26: undefined reference to `_nfc_configure'
/cygdrive/c/NetBeans/LibNFC/LibNFCNative/LibNFC.c:27: undefined reference to `_nfc_configure'
/cygdrive/c/NetBeans/LibNFC/LibNFCNative/LibNFC.c:30: undefined reference to `_nfc_configure'
collect2: ld returned 1 exit status


I'm correctly identifying the library path for libnfc in both cases, and I've tried the library version for Win and Linux. Why is Cygwin messing this up for me? Sorry for the long post.
Re: Processing and the libnfc library in C
Reply #2 - Jan 25th, 2010, 2:47am
 
I have no experience in this domain (JNI, etc.) and no device to test on. But I will try to help a bit anyway.

Quote:
I have in libraries in C:\cygwin\usr\include

I don't know Cygwin, but in general 'include' folder is to put .h files. Also I don't see reference to the libNFC object files in the command line. Just to be sure we don't forget something, ensure you have compiled the whole project and it is available and referenced as .o file.
Re: Processing and the libnfc library in C
Reply #3 - Jan 25th, 2010, 3:43am
 
PhiLho  wrote on Jan 25th, 2010, 2:47am:
I have no experience in this domain (JNI, etc.) and no device to test on. But I will try to help a bit anyway.

Quote:
I have in libraries in C:\cygwin\usr\include

I don't know Cygwin, but in general 'include' folder is to put .h files. Also I don't see reference to the libNFC object files in the command line. Just to be sure we don't forget something, ensure you have compiled the whole project and it is available and referenced as .o file.


I smell a noob mistake on my part Embarrassed Having the .c and .h files for the library in C:\cygwin\usr\include isn't enough I have to compile the libnfc library as I compile the rest of my code

By the way, since it's compiling in Cygwin, should I use the Linux or Windows libNFC library (http://www.libnfc.org/download/)

Thanks for your help so far Smiley
Re: Processing and the libnfc library in C
Reply #4 - Jan 25th, 2010, 5:28am
 
First, on Cygwin: I stay away from it... Smiley It is a fine library, quite practical to quickly compile Unix programs on Windows, but I believe it adds quite an overhead to applications compiled with it (a quite large DLL), since it tries to emulate Unix on Windows.

So I stick to MinGW compiler, which is GCC without Cygwin. I recently installed the distribution at TDM's GCC/mingw32 Builds, it is quite large (no more than Processing!) but it works fine.
In any case, I think you must use the Windows download. Or just do the binaries yourself!

Compilation of C code isn't trivial, as you discovered.
The description of the download says: "Binary (lib,dll) files for Windows".
The DLL contains the library in a kind of application independent way.
The lib can be of two kinds: the first kind is a strict minimum holding information on the functions in the DLL, allowing the linker to link against the DLL. The generated executable will be smaller but will need the DLL. That's dynamic linking (DLL means, IIRC, Dynamically Linked Library or something like that -- the equivalent in the Unix world is .so files).
The second kind contains all the library (it is bigger) and when you link against it, the produced executable would need no DLL as it embeds the library. It is probably a better solution in your case. That's static linking.

I think the best way to go is to compile libNFC as instructed, to produce a library file for static linking.
Then you can compile your test.c. Compiler will need the .h files, to know how the functions look like. Unless explicitly instructed (eg. in a make file), it won't compile the .c files itself.
Then you link, grouping together the test code and the library code.

I hope I was clear, I fear to spread more confusion than clarity... Smiley
Re: Processing and the libnfc library in C
Reply #5 - Jan 25th, 2010, 8:31am
 
Confusing or not, I'm just glad you took the time to explain me this Smiley I'll follow your advice regarding the static linking.

I've downloaded the MinGW version you posted, but I wonder if you know what kind command I must use in NetBeans to mimic this one I used for Cygwin:

Code:
-mno-cygwin -Wl,--add-stdcall-alias -shared -m32 



Hope I'm getting your idea straight, I now must also add the "include" folder from the binary files (that has all the *.h) to NetBeans so everything will be compiled together?
Re: Processing and the libnfc library in C
Reply #6 - Jan 26th, 2010, 6:05am
 
I have no experience with compiling C with NetBeans, I use Visual Studio or the command line...
Visual Studio Express is free and another way to compile the project (I see the libnfc-1.3.1-winsdk.zip (released yesterday!) have a Makefile for this environment. That's yet another compiler/IDE to download and install, so maybe you might prefer to stick to NetBeans...

I think you must do a project whose output is a library to link against (so, as I explained, not a library to link with in order to use a DLL). You just add the source code files to your project, and it should work.
Then you can make another project, referencing the generated lib file.
An alternative is to just put all the files (of libnfc and your) together in a small project.
Note: a glance at the read me file suggests you might need another project to compile this one (libUSB).
Re: Processing and the libnfc library in C
Reply #7 - Jan 27th, 2010, 5:21pm
 
Thanks for warning me about the release of the version 1.3.1 of libnfc. Unfortunately I still use Windows XP on my "work" laptop :/

I've been able to use Visual Studio to compile a C file that uses libnfc (and libusb), but when I adapt the code to work with JNI, changing the main to:

Code:
JNIEXPORT jstring JNICALL Java_libnfc_Main_nativeTagID(JNIEnv *env, jobject obj) 

(for example)

I'm getting an error related to the libNFCNative.h. This file is supposed to aid in the creation of the dll file that the Java then uses to call functions from C.

The .h file has:

Code:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class libnfc_Main */

#ifndef _Included_libnfc_Main
#define _Included_libnfc_Main
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     libnfc_Main
* Method:    nativeTagID
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_libnfc_Main_nativeTagID
 (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


The error is as follows:

Code:
------ Build started: Project: nfc-list, Configuration: Debug Win32 ------
Linking...
  Creating library C:\Documents and Settings\Augusto\Desktop\libnfc-1.2.1-vs2005\vc-project\Debug\libNFCNative.lib and object C:\Documents and Settings\Augusto\Desktop\libnfc-1.2.1-vs2005\vc-project\Debug\libNFCNative.exp
MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
C:\Documents and Settings\Augusto\Desktop\libnfc-1.2.1-vs2005\vc-project\Debug\libNFCNative.dll : fatal error LNK1120: 1 unresolved externals


I've tried SWIG instead of JNI, but I'm having the exactly same error in Visual Studio.

Using Netbeans I simply can't compile a C file that uses libnfc (and libusb), because the binaries are giving me errors like: Headers only work with Visual Studio.

I'm now trying to compile a simple C file that uses libnfc, using only the command line (MinGW), but it seems it will be very tricky :/ Do you know any good documentation or tutorial for working with libraries such libnfc?

Thanks again for all your help Smiley

Re: Processing and the libnfc library in C
Reply #8 - Jan 28th, 2010, 2:00am
 
I fear I don't know a good tutorial but there are probably plenty on the Net...
I don't know much JNI either. But the error you show suggests the compiler tries to make an exe file, expecting to find a main() function that would be the starting point of such executable.
So you have probably used the wrong project type, as you don't try to generate a .exe file but rather a .dll to use by your Java project.
Re: Processing and the libnfc library in C
Reply #9 - Feb 2nd, 2010, 2:40pm
 
You're absolutely right Smiley I'm so close, but I keep having such basic problems. I have changed both the SWIG and the JNI Visual Studio projects to generate a .dll instead of an .exe, but I'm still having the same sort problem (with both SWIG and JNI):

MSVCRT.lib(crtexe.obj) : error LNK2001: unresolved external symbol _main

According to this website: http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/e7787ddd-9526-4ed7-bd51-8ccf8dd44133

this is because I don't have a main and/or I was doing this in an Empty Project (instead of a Win32 Console or Win32 Project). Problem is, when I create a Win32 Project I start getting this error with the LibNFCNative.h (which is to be used by JNI):

fatal error C1853: 'Debug\LibNFCNative.pch' precompiled header file is from a previous version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa)

I assume JNI only works with pure C, so is there a way of creating such project in Visual Studio?

(I know I'm stretching my welcome, just hope you can bare with a couple of more questions from me PhiLho Embarrassed)


Re: Processing and the libnfc library in C
Reply #10 - Feb 3rd, 2010, 5:08am
 
You can deactivate the pre-compiled headers (I always do that...) in the project. You can then delete the .pch file.

You also have to create a pure C project (I don't recall if this option is still available).
Another way is to put in the .h file:
Code:
#ifdef __cplusplus
extern "C"
{
#endif

/* Declarations */

#ifdef __cplusplus
}
#endif


I don't mind the questions, I am just sorry not being able to help you more.
Re: Processing and the libnfc library in C
Reply #11 - Feb 7th, 2010, 5:46pm
 
Hum, still not working :/ There's no option to create a "pure" C project, and even when I choose Not Using Precompiled Headers I get the same error:

Code:
Compiling...
libNFC-java.c
.\libNFC-java.c : fatal error C1853: 'Release\libNFC-java.pch' precompiled header file is from a previous version of the compiler, or the precompiled header is C++ and you are using it from C (or vice versa)


Regarding your other solution, the .h that works with JNI already looks like code you wrote:

Code:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class libnfcjava_Main */

#ifndef _Included_libnfcjava_Main
#define _Included_libnfcjava_Main
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     libnfcjava_Main
* Method:    nativeTagID
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_libnfcjava_Main_nativeTagID
 (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


Do I need to add the ifdef __cplusplus to every other .h file? You can see my Project tree here:

...

Everything but the LibNFCNative.h and the .c is automatically generated when I choose to create a Win32 Project. My libNFC-java.c has only:

Code:
// libNFC-java.c : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "libnfc.h"
#include "LibNFCNative.h"
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <jni.h>

JNIEXPORT jstring JNICALL Java_libnfcjava_Main_nativeTagID(JNIEnv *env, jobject obj) {

dev_info* pdi;
// tag_info ti;
char buf[64];

// Try to open the NFC reader
pdi = nfc_connect();
 
if (pdi == INVALID_DEVICE_INFO) {
buf[0] = "Failure";
} else buf[0] = "Success";

return (*env)->NewStringUTF(env, buf);
}
Re: Processing and the libnfc library in C
Reply #12 - Feb 8th, 2010, 7:57am
 
Quote:
even when I choose Not Using Precompiled Headers I get the same error
Have you tried to delete the .pch file by hand?
Re: Processing and the libnfc library in C
Reply #13 - Feb 8th, 2010, 4:48pm
 
PhiLho  wrote on Feb 8th, 2010, 7:57am:
Quote:
even when I choose Not Using Precompiled Headers I get the same error
Have you tried to delete the .pch file by hand


Problem is I was changing the options related to Debug, but not Release Embarrassed I finally was able to compile a Java code that checks if a RFID reader is connected to the computer. Next step is to check the ID of an RFID Tag.

You were really helpful, thanks a lot, really Smiley

Do you know if there's a tutorial on how to get my Java code running from Processing
Re: Processing and the libnfc library in C
Reply #14 - Feb 9th, 2010, 1:52am
 
Quote:
I was changing the options related to Debug, but not Release

Yes, it still happens to me from time to time... Smiley

Quote:
how to get my Java code running from Processing

It is trivial... Smiley
Just add the .java file to the sketch, then you can use the class(es) defined there.
You need to drop the DLL and jar files you created on the PDE opening the sketch, it will copy them into a 'code' folder in the sketch folder.
Pages: 1 2