Hmm. I assume #add_collision_func is a compatibility function that wraps the now very old Chipmunk API function of the same name. The way that worked is that it would call the callback for every frame that things are overlapping. Without seeing more code (yours and the binding), I can't say either way if this was happening or not.
There should be something that wraps the much newer collision handler functionality (cpSpaceAddCollisionHandler()) which lets you register separate begin, preSolve, postSolve, and separate callbacks. Begin callbacks are guaranteed to be called only once.